2

How can I create a type with the keys from a Map?

export const languageOptionsMap = new Map<string, ILanguageOption>([
    [
        'cs',
        {
            value: 'cs',
            order: 1,
            text: 'Česky',
        },
    ],
    [
        'en',
        {
            value: 'en',
            order: 2,
            text: 'English',
        },
    ],
]);

I want to generate the type LanguageCode without having to repeat the keys of the map as I do below:

export type LanguageCode = 'cs' | 'en';
user1283776
  • 19,640
  • 49
  • 136
  • 276

1 Answers1

2

After passing the data to the map we can't extract the type information. If we put the data in a separate variable and use a const assertion (in 3.4) to make sure typescript keeps string literal types we can extract the type information from there:

const data = [
    [
        'cs',
        {
            value: 'cs',
            order: 1,
            text: 'Česky',
        },
    ],
    [
        'en',
        {
            value: 'en',
            order: 2,
            text: 'English',
        },
    ],
] as const
export const languageOptionsMap = new Map<string, ILanguageOption>(data);
export type LanguageCode = typeof data[number][0]
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • 1
    Whenever I see `Map` I wonder why someone isn't using a plain object type. In this case, the constraint that `languageOptionsMap.get(key).value === key` cannot be represented with the `Map` interface, but could be expressed as a mapped type like `const asLanguageOptions = (t: T) => t;`. ‍♂️ – jcalz Apr 18 '19 at 11:18
  • 1
    @jcalz Fully agreed about the plain object, much simpler IMO. And indeed the assumption that `languageOptionsMap.get(key).value === key` is unchecked. But hey I just provide the for the :) – Titian Cernicova-Dragomir Apr 18 '19 at 11:25