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'}),
}
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
}