How to convert recieved string to enum

Viewed 55

I am receiving some json object from a file, and I want to parse some of the fields to predefined values.

import jobsRaw from '../../data/jobs.json';

I created a type that describes my object, but I want the status to have only my predefined values, if else I might define a fallback value.

export type Job = {
  type: string;
  id: string;
  status: JobStatus;
  warehouseId: string;
  relatedCell: string;
  relatedDocument: string;
  partnerName: string;
  potatoType: string;
  relatedBoxes: string[];
  boxCount?: number;
  createdAt: string;
  completedAt: string;
};

This is the mapping I'm trying with:

const jobs: Job[] = jobsRaw.map((job: Job) => ({
  ...job,
  status: JobStatus[job.status],
  boxCount: job.relatedBoxes.length,
}));

I want to create some sort of JobStatus type that I can parse my received string value with.

1 Answers

If I had to implement this I would go for a type predicate to check if the data is a proper JobStatus. Maybe something like this:

const isJobStatus = (value: any): value is JobStatus =>
  value && Object.values(JobStatus).includes(value);

const jobs: Job[] = jobsRaw.map((job: Job) => ({
  ...job,
  status: isJobStatus(job.status) ? job.status : JobStatus.SOME_DEFAULT_STATUS,
  boxCount: job.relatedBoxes.length,
});

With this approach you could even use a different type in map iterator like below to better represent the "raw" data because the type predicate will cast job.status as a proper JobStatus when it returns true. I've also made boxCount mandatory in Job and removed it from JobRaw, by doing like this you won't need to make it optional.

export type Job = {
  type: string;
  id: string;
  status: JobStatus;
  warehouseId: string;
  relatedCell: string;
  relatedDocument: string;
  partnerName: string;
  potatoType: string;
  relatedBoxes: string[];
  boxCount: number;
  createdAt: string;
  completedAt: string;
};

type JobRaw = Omit<Job, 'status' | 'boxCount'> & { status: string };

const jobs: Job[] = jobsRaw.map((job: JobRaw) => ({
  ...job,
  status: isJobStatus(job.status) ? job.status : JobStatus.SOME_DEFAULT_STATUS,
  boxCount: job.relatedBoxes.length,
}));
Related