While working with intersection types in an Angular template, I faced a challenge. In my component's TypeScript file, I defined the following input:
export class ExampleClassComponent {
...
@Input() items: Array<InfoItem> | Array<InfoItemWithAction> = [];
...
}
Where InfoItem is an interface and InfoItemWithAction is an intersection type described as follows:
export interface InfoItem {
value: string;
name?: string;
}
export type InfoItemWithAction = InfoItem & { action: ActionType; id: number };
When iterating over the items array within my template file, each item narrows down to only "value" and "name", as these properties match in both parts.
<ul>
<li *ngFor="let item of items">
<div>
{{ item.name }} {{ item.value }}
</div>
<button *ngIf="item.action" (click)="onActionClicked(item)"> --> throws unknown property "action"
<span [class.color]="item.action === 'delete' ? 'warn' : null"> --> throws unknown property "action"
{{ item.action }} --> throws unknown property "action"
</span>
</button>
</li>
</ul>
This behavior is logical, but I couldn't find a solution to this issue.
I attempted using a type guard, but it resulted in a function check every time I needed to access item.action, which appeared cumbersome.
Using item['action'] as an index type was not a viable option either.
Creating a new component for each type crossed my mind, but I prefer avoiding that approach.
Does anyone have any suggestions?