When utilizing the iterator *ngFor
, it converts a string union literal type
("apple" | "banana")
to a string type. However, when attempting to use it as an index of an array expecting the correct string union literal type, an error occurs:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'FruitCollection'.
apple-banana-component.ts
:
import { Component, OnInit } from '@angular/core';
const Fruits = ["apple", "banana"] as const;
type Fruit = typeof Fruits[number]; // "apple" | "banana"
type FruitCollection = { [fruit in Fruit]: number }; // {apple: number, banana: number}
@Component({
selector: 'app-apple-banana',
templateUrl: './apple-banana.component.html'
})
export class AppleBananaComponent implements OnInit {
fruitBasket: FruitCollection = {
apple: 10,
banana: 10
}
fruitEaten: FruitCollection = {
apple: 0,
banana: 0
}
constructor() { }
ngOnInit(): void { }
eatFruit(fruit: Fruit) {
this.fruitEaten[fruit]++;
this.fruitBasket[fruit]--;
}
}
apple-banana-component.html
:
<div>
You have eaten {{fruitEaten['apple']}} apples and {{fruitEaten['banana']}} bananas.
<div *ngFor="let fruit of fruitBasket | keyvalue">
{{fruit.key}}:
{{fruit.value}} in basket,
{{fruitEaten[fruit.key]}}
eaten.
<button (click)="eatFruit($any(fruit.key))">eat {{fruit.key}}</button>
</div>
</div>
Oddly enough, $any(fruit.key)
works inside eatFruit()
but not within fruitBasket[]
.
{{fruitEaten[fruit.key as Fruit]}}
{{fruitEaten[fruit.key as keyof typeof fruitEaten]}}
{{fruitEaten[$any(fruit.key)]}}