What is the index type of const object in TypeScript?

1.2k Views Asked by At

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?

2

There are 2 best solutions below

1
On BEST ANSWER

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];
0
On

Why won't Readonly<string> works in the case above?

Because your object does not have a key for all possible string.

'bar' is a string, but when you access foo['bar'] you get undefined, not an array of strings, so your type would not make sense.

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 assign it to an intermediate type if you need to use it in different places:

type FooKeys = keyof typeof foo
type RandomType = typeof foo[FooKeys][number];