typescriptunion-types

Get type of values of a const object when the object has a type annotation


I have a union and object like this:

type FilterType = 'equals' | 'notEquals';

const labelMap: {[filterType in FilterType]: string} = {
    equals: 'Equals',
    notEquals: 'Not Equals',
} as const;

And I would like to derive from this the equivalent of:

type Labels = 'Equals' | 'Not Equals';

The closest I've been able to get to this is:

type Labels = labelMap[keyof labelMap];

This works if I remove the {[filterType in FilterType]: string} annotation, but I'd like to keep that so if we add new filters, we'll be forced to add a label.

How can I annotate the type of the keys of the object and also extract out the values? I could make the values their own explicit type then use:

const labelMap: {[filterType in FilterType]: ValueType} = {

But I'd prefer to keep it centralized if possible so you don't need to go to multiple places just to add a new filter.


Solution

  • Just use the satisfies operator:

    type FilterType = 'equals' | 'notEquals';
    
    const labelMap = {
        equals: 'Equals',
        notEquals: 'Not Equals',
    } as const satisfies Record<FilterType, string>;
    

    If you add a new element to the union you'll see an error if you don't add the corresponding entry in labelMap.

    Playground

    Note that your annotation is "wrong":

    type MappedType = {[filterType in FilterType]: string}
    
    const bad: MappedType = {
        equals: 'Not Equals',
        notEquals: 'Equals',
    } // Oops!
    

    Since it doesn't preserve the mapping between keys and values!

    Playground