I would like to define a type based on values of an Object.
For example,
const foo = <const>{
'a': ['1', '2', '3', '4'],
'b': ['5', '6', '7', '8'],
'c': ['9', '10', '11', '12'],
};
type RandomType = typeof foo[Readonly<string>][number]; // '1' | '2' | '3' | ... | '12'
But TypeScript reports the following error if I use number
as the index type
Type '{ readonly a: readonly ["1", "2", "3", "4"]; readonly b: readonly ["5", "6", "7", "8"]; readonly c: readonly ["9", "10", "11", "12"]; }' has no matching index signature for type 'string'.ts(2537)
A workaround is replacing Readonly<string>
with keyof typeof foo
type RandomType = typeof foo[keyof typeof foo][number];
But it makes the statement longer and harder to read, especially if the object I use is nested within another object, like aaa.bbb.ccc.ddd.foo
.
Why won't Readonly<string>
works in the case above?
Is keyof typeof foo
the shortest form to describe 'a' | 'b' | 'c'
? Is there any type to replace it and make the statement easier to read?
You can use Values
utility type.
const foo = {
'a': ['1', '2', '3', '4'],
'b': ['5', '6', '7', '8'],
'c': ['9', '10', '11', '12'],
} as const;
type Values<T> = T[keyof T]
type RandomType = Values<typeof foo>[number];