Angular模板中使用交叉类型遇类型收窄问题求解决方案
解决Angular模板中交叉类型访问的问题
以下是几种无需拆分组件、避免重复类型检查的可行方案:
方案1:修改数组类型为元素联合类型+单次类型守卫
首先调整输入属性的类型,将数组的联合类型改为元素的联合类型,让模板能识别每个item的完整联合类型:
export class ExampleClassComponent { // 修改为元素级别的联合类型 @Input() items: Array<InfoItem | InfoItemWithAction> = []; // 定义类型守卫函数 isInfoItemWithAction(item: InfoItem | InfoItemWithAction): item is InfoItemWithAction { return 'action' in item && 'id' in item; } }
模板中利用*ngIf的as语法,仅调用一次守卫就复用收窄后的变量:
<ul> <li *ngFor="let item of items"> <div> {{ item.name }} {{ item.value }} </div> <ng-container *ngIf="isInfoItemWithAction(item) as actionItem"> <button (click)="onActionClicked(actionItem)"> <span [class.warn]="actionItem.action === 'delete'"> {{ actionItem.action }} </span> </button> </ng-container> </li> </ul>
方案2:直接在模板中进行类型收窄
无需额外定义守卫函数,直接在模板中用in操作符判断属性存在,配合as语法复用变量:
<ul> <li *ngFor="let item of items"> <div> {{ item.name }} {{ item.value }} </div> <ng-container *ngIf="'action' in item && 'id' in item as actionItem"> <button (click)="onActionClicked(actionItem)"> <span [class.warn]="actionItem.action === 'delete'"> {{ actionItem.action }} </span> </button> </ng-container> </li> </ul>
方案3:临时绕过类型检查(不推荐长期使用)
如果只是临时调试或快速验证,可使用Angular模板的$any()函数跳过类型检查:
<ul> <li *ngFor="let item of items"> <div> {{ item.name }} {{ item.value }} </div> <button *ngIf="$any(item).action" (click)="onActionClicked($any(item))"> <span [class.warn]="$any(item).action === 'delete'"> {{ $any(item).action }} </span> </button> </li> </ul>
注意:此方法会丢失TypeScript的类型安全保障,仅适合临时场景。
内容的提问来源于stack exchange,提问作者Urastor
相关产品推荐
相关产品推荐

