Reputation: 2700
I'm trying to create a function that constructs and returns an object with properties that match the array of strings passed in the params.
type Foods = 'apple' | 'banana' | 'pear';
function foodObjects<K extends Foods>(foods: Foods[]): Record<K, number> {
const ret = {};
foods.forEach((food, i) => {
ret[food] = i;
})
return ret;
}
foodObjects(['apple', banana']); // should return { apple: 0, banana: 1 }
In this simple example, you pass it an array of fruits and it returns an object with the fruit names as keys. However, I get a warning when defining the ret
variable (const ret = {};
):
Type '{}' is not assignable to type 'Record<K, number>'
I can resolve that error with the as
keyword, but this doesn't feel correct:
const ret = {} as Record<K, number>;
Upvotes: 0
Views: 508
Reputation: 11558
If you want an array to turn into an object, your best bet is to reduce it:
type Foods = "apple" | "banana" | "pear";
function foodObjects<K extends Foods>(foods: Foods[]): Record<K, number> {
return foods.reduce((acc, food, i) => ({ ...acc, [food]: i }), <Record<K, number>>{});
}
console.log(foodObjects(["apple", "banana"])); // should return { apple: 0, banana: 1 }
Since it was pointed out that casting is not super ideal, here is a version that does not need casting:
type Foods = "apple" | "banana" | "pear";
type FoodObjects = {
[K in Foods]: number;
};
function foodObjects(foods: Foods[]): FoodObjects {
const entries = foods.map((food, i) => [food, i]);
return Object.fromEntries(entries);
}
Upvotes: 2