While working on a TypeScript project, it is a common ask to restrict a type of variable to the value of the keys of an object.
Suppose we have an object like the below:
const statusMap = { pending : 'PENDING', finished : 'FINISHED', notStarted : 'NOT_STARTED'
};
When we want to have a related status
variable, it can only have three values – PENDING, FINISHED and NOT_STARTED.
The way to go about it is usually by narrowing the type of our object first:
const statusMap = { pending : 'PENDING', finished : 'FINISHED', notStarted : 'NOT_STARTED'
} as const;
Using as const
or const assertion,
- we make
statusMap
read-only, eg:statusMap.pending
cannot be modified. - no literal types are widened. eg: type
PENDING
does not becomestring
So given the above we usually end up creating a type like:
We use keyof
and typeof
provided by Typescript and Javascript respectively to help us make the suitable type.
This works well. But I would like to avoid writing the variable statusMap
twice. Imagine us having multiple variables like that and our code starts looking like this:
It would be great if we could simplify it and reduce the duplication.
To do that it is easy to create a type like below:
type valueof<X> = X[keyof X];
We have created a generic called valueof
. We extract the values of the keys of type X and use them to make a template literal type.
Now it works like the below and still works.
valueOf
seems so convenient that I am surprised it is not available in TypeScript out-of-the-box. I hope you guys also find use of it.