Home > front end >  How to reference the key of `Record<>` in the record value
How to reference the key of `Record<>` in the record value

Time:04-21

Given the following MyKey type

type MyKey = 'alpha' | 'beta' | 'charlie' | 'delta'

I'd love to define a Record type where each key must be present AND each value must be a function that returns an object with name property that is the same as the key.

Here's my best attempt

type MyRecords = Record<MyKey, () => {name: MyKey}>

const example: MyRecords = {
    'alpha': () => ({name: 'beta'}),
    'beta': () => ({name: 'beta'}),
    'charlie': () => ({name: 'beta'}),
    'delta': () => ({name: 'beta'}),
}

But the issue here is that all records are content to any MyKey (beta in this case) as the name value. I want to constrain it to

const example: MyRecords = {
    'alpha': () => ({name: 'alpha'}),
    'beta': () => ({name: 'beta'}),
    'charlie': () => ({name: 'charlie'}),
    'delta': () => ({name: 'delta'}),
}

typescript playground

CodePudding user response:

You don't want to use the Record<K, V> utility type here at all, as it does not represent a relationship between the specific key types and value types. If you use Record<K, V>, all properties will be of the same type.

Instead you should just write your own mapped type where you refer to the key type parameter inside the property type. Like this:

type MyRecords = { [K in MyKey]: () => { name: K } }
/* type MyRecords = {
    alpha: () => {
        name: "alpha";
    };
    beta: () => {
        name: "beta";
    };
    charlie: () => {
        name: "charlie";
    };
    delta: () => {
        name: "delta";
    };
} */

That's the type you want, and it behaves how you want with your example:

const example: MyRecords = {
    'alpha': () => ({ name: 'beta' }), // error
    'beta': () => ({ name: 'beta' }), // okay
    'charlie': () => ({ name: 'beta' }), // error
    'delta': () => ({ name: 'beta' }), // error
}

Playground link to code

  • Related