I’m trying to change the shape of Item
to meet a complex interface NewItem
by calling transformData()
. However I’m getting the following error.
The error message is "Element implicitly has an ‘any’ type because expression of type ‘string’ can’t be used to index type ‘{}’." Here’s a simplified version of my code that still produces the error:
interface Item {
itemName: ItemName;
quantity: number;
itemBreakdown ? : [];
}
type ItemName = 'Dog' | 'Plant' | 'Unknown'
interface NewItem {
animal: number;
plant: number;
food: number;
unknown: number;
itemBreakdown ? : {
catergory1 ? : [ItemDetails]
catergory2 ? : [ItemDetails]
};
error ? : Error | Error[]
}
private transformData(items: Item[]): NewItem {
const newItem: NewItem = {};
items.reduce((acc, item) => {
const { itemName, quantity } = item;
// Error thrown by line below
acc[this.mapItemName(itemName)] = quantity;
return acc;
}, newItem);
return newItem;
}
private mapItemName(itemName: string): string {
switch (itemName) {
case 'Dog':
return 'animal';
case 'Plant':
return 'plant';
default:
return 'unknown';
}
}
TS7053: Element implicitly has an any type because expression of type string can't be used to index type NewItem
No index signature with a parameter of type string was found on type NewItem
I think I understand the issue but I’m not sure what’s the right way to solve it.
The issue is that I’m passing in a key of type string to {}: NewItem
, where NewItem has no index signature of key[string] : number
.
I can’t assign key[string] : number
to NewItem Interface because what about the other values?
I don’t want to set type as any either or turn off strict mode.
What’s the correct way to solve this without losing type safety?
2
Answers
Silly me all I had to do was not to define a return type...
Your
mapItemName
should be of the type ofkeyof NewItem
. Moreover we can mapItemName
to a new typeNewItemKey
ensuring the result exists inNewItem
‘s keys:Playground
But the whole construct isn’t type safe, using
{} as Newitem
we skip required fields animal, plant, etc. Either make them optional or ensure thatItem[]
passed totransformData
contains all items needed to fillNewItem
properly (I guess that’s not something trivial but achievable).