Reputation: 8690
I have an object of objects like:
const CATEGORIES = {
diet: {
id: 'diet',
title: 'Diet',
...
},
...
}
How can I write a type for it so that TypeScript will ensure that the nested id
property will match the object's key in the parent?
I've tried...
const CATEGORIES: {
[T in string]: {
id: T
title: string
}
} = { ... }
...but this seems to still accept any strings for id
.
I'm assuming it uses mapped types and generics somehow, but I can't quite figure out what the syntax is, if it's even possible.
Upvotes: 1
Views: 125
Reputation: 327754
You can't map over all of string
and have it act the way you want here; see microsoft/TypeScript#22509. You'll need a set of string literal keys to map over. One way to achieve this is to use a generic helper function which infers those keys from the passed-in value, and verifies that the id
subproperty of each property matches its key:
const asCategories = <T extends { [K in keyof T]: { id: K, title: string } }>(t: T) => t;
You can test to see that it's happy with good values:
const CATEGORIES = asCategories({
diet: {
id: 'diet',
title: 'Diet',
//...
},
//...
}); // okay
and angry with bad ones:
const BADCATEGORIES = asCategories({
diet: { id: "diet", title: "Diet" },
exercise: { id: "exersice", title: "Exercise" } // error!
// -------> ~~
// Type '"exersice"' is not assignable to type '"exercise"'.
})
Okay, hope that helps; good luck!
Upvotes: 1