Reputation: 41605
I'm having trouble when I try to update an Object's property based on a dynamic variable. I've checked a few more answers on stackoverflow but couldn't manage to find a solution.
export interface Bikes {
totals: Array<number>;
}
interface Products {
cars: Cars;
bikes: Bikes;
}
export interface RawData {
products: Products
}
demo( data: RawData ) {
// data.products contains both "cars" and "bikes" properties.
for (var type in data.products) {
for (var product in data.products[type].totals) {// <-- error here
-------------
....
}
}
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Products'. No index signature with a parameter of type 'string' was found on type 'Products'.
I've also tried using:
export interface RawData {
products: keyof Products
}
And then the error appears on data.products[type].totals
Property 'bikes' does not exist on type 'string'.
Upvotes: 1
Views: 120
Reputation: 33051
In your case, variable type
is infered to string
.
TS disallows you to use string
type as index of RawData['products']
type.
If you want to assure TS that you can do it, you have two ways:
1) Make type assertion
function demo(data: RawData) {
for (const type in data.products) {
// explicitly define type for `type` varable
for (const product in data.products[type as keyof RawData['products']]) { // ok
}
}
}
2) Make Products indexable
interface Products {
cars: Cars;
bikes: Bikes;
[prop: string]: Cars | Bikes
}
UPDATE
interface Bikes {
totals: Array<number>;
}
type Mix = { foo: 'a' };
type Products = {
cars: Cars;
bikes: Bikes;
mix?: Mix;
}
type Values<T> = T[keyof T]
type MakeIndexed<T> = T & { [prop: string]: Values<T> }
interface RawData {
products: MakeIndexed<Products>
}
function demo(data: RawData) {
for (const type in data.products) {
for (const product in data.products[type]) { // ok
}
}
}
Upvotes: 2