Angular ngIf警告:'length'未定义问题排查求助
Angular Template Type Check Warning: 'length' is not defined on 'Transfer[] | AppResponseError'
这个警告的根源在于TypeScript的联合类型检查逻辑。你的transfers变量是Transfer[] | AppResponseError的联合类型,当你尝试访问transfers?.length时,TypeScript会检查联合类型中的所有成员是否都拥有length属性——显然AppResponseError并没有这个属性,所以即便运行时不会报错,编译阶段TypeScript会抛出这个警告来提醒你类型的不确定性。
而且Angular模板的类型推断目前还没智能到自动根据transfers?.length > 0这个条件来缩小类型(也就是自动判断此时transfers一定是Transfer[]),所以我们需要手动帮TypeScript明确类型。
解决方法1:使用类型守卫函数(最健壮的方式)
在你的组件类里定义一个类型守卫函数,用来明确判断传入的值是否是Transfer[]:
// 在 TransferComponent 类中添加 isTransferArray(data: Transfer[] | AppResponseError): data is Transfer[] { return Array.isArray(data); }
然后在模板中用这个函数做条件判断,TypeScript会自动推断出符合条件的transfers就是数组类型:
<div *ngIf="transfers$ | async; let transfers; else loadingTpl"> <!-- 先判断是否为错误对象 --> <ng-container *ngIf="!isTransferArray(transfers); else listContent"> <ng-container *ngTemplateOutlet="error; context:transfers"></ng-container> </ng-container> <ng-template #listContent> <app-checklist *ngIf="transfers.length > 0" [items]="transfers"> <div *ngFor="let transfer of transfers"> ..something here </div> </app-checklist> <ng-container *ngTemplateOutlet="emptyList; context: {length: transfers.length}"></ng-container> </ng-template> </div>
解决方法2:利用属性检查缩小类型(快速简便)
因为AppResponseError拥有code属性而Transfer[]没有,你可以通过检查是否存在code来区分两种类型:
<div *ngIf="transfers$ | async; let transfers; else loadingTpl"> <!-- 错误状态 --> <ng-container *ngIf="transfers.code"> <ng-container *ngTemplateOutlet="error; context:transfers"></ng-container> </ng-container> <!-- 列表状态(此时TypeScript知道transfers是Transfer[]) --> <ng-container *ngIf="!transfers.code"> <app-checklist *ngIf="transfers.length > 0" [items]="transfers"> <div *ngFor="let transfer of transfers"> ..something here </div> </app-checklist> <ng-container *ngTemplateOutlet="emptyList; context: {length: transfers.length}"></ng-container> </ng-container> </div>
额外修复:接口定义语法错误
注意你的组件类里接口定义有语法错误,应该使用标准的接口声明方式,去掉=:
export interface AppResponseError { code: number; title: string; message: string; } export interface Transfer { id: number; title: string; }
内容的提问来源于stack exchange,提问作者Doug
相关产品推荐
相关产品推荐

