I want to enforce all the values on an object literal be a certain type. However I want to be able to set any string key name. And then I want to infer the type of that object literal.
Here is an example:
type Fruit = 'apple' | 'banana' | 'pear'
const list = {
eat: 'apple',
save: 'banana',
sell: 'pear',
}
type FruitKey = keyof typeof list
type FruitDetails = { [key in FruitKey]: Fruit }
const fruitDetails = list as FruitDetails
This example isn’t quite right because it does not ensure each value is of type Fruit, I could add give: 'pizza' to the list and it would not compain.
I could define it like so:
const list: {[k in string]: Fruit} = {
eat: 'apple',
save: 'banana',
sell: 'pear',
}
This will ensure only fruit are added but now I can no longer infer the keys for my FruitKey which now just becomes type string.
Is there a way to achieve this?
>Solution :
You can use satisfies probably
const myFruits = {
eat: 'apple',
save: 'banana',
sell: 'pear',
cook: 'pizza', //Type '"pizza"' is not assignable to type 'Fruit'.(2322)
} satisfies Record<string, Fruit>
type T = typeof myFruits //gives exact type
or if you prefer with a generic function it works well
const makeFruits = <T extends Record<string,Fruit>>(value: T)=>value
makeFruits({
eat: 'apple',
save: 'banana',
sell: 'pear',
make: 'pizza', //Type '"pizza"' is not assignable to type 'Fruit'.(2322)
})