Search code examples
typescripttypescript-typingstypeofkeyof

What is the index type of const object in TypeScript?


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?


Solution

  • 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];