1

I have this static array that may grow over time. Eg maybe in a month I will add another entry.

const GROUPS = ['Objects', 'Things', 'Stuff']

All of these refer to an interface, such as

interface Group { name: string, level: number}

How do I make a TS type that maps it with only the allowed const strings?

type GroupType = {[key: GROUPS]: Group}

1 Answer 1

2

First, in order for the compiler to keep track of the literal types of the elements of GROUPS and not just string, you should use a const assertion when you initialize it:

const GROUPS = ['Objects', 'Things', 'Stuff'] as const;
// const GROUPS: readonly ["Objects", "Things", "Stuff"]

You can see that GROUPS's type is now a readonly tuple consisting of literal types.

Once you do that you can define GroupType as a mapped type over the union of elements of the GROUPS array, by indexing into the type typeof GROUPS (using the typeof type operator) with a number index (since the type you get when accessing GROUPS[n] where n is of type number is a union of the element types):

type GroupType = { [K in typeof GROUPS[number]]: Group }
/* type GroupType = {
    Objects: Group;
    Things: Group;
    Stuff: Group;
} */

You could also write this out like:

type GROUPS = typeof GROUPS[number];
type GroupType = Record<GROUPS, Group>;
/* type GroupType = {
    Objects: Group;
    Things: Group;
    Stuff: Group;
} */

where we give a type named GROUPS to the element types of the GROUPS value, and we use the Record<K, V> utility type instead of the equivalent manually-written mapped type.

Playground link to code

Sign up to request clarification or add additional context in comments.

2 Comments

Does this work if I already have an array defined? ie const GROUPKEYS = [...GROUPS] as const.. Doesn't seem to work. I mean, it compiles, but does not show the keys.
No. as const tells the compiler to preserve some of the information it would have otherwise thrown away. By the time you write [...GROUPS] as const apparently GROUPS has already been created and the info you need thrown away. as const doesn't resurrect dead information.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.