我可以在Angular模板中进行类型缩小吗?

时间:2017-11-10 10:41:07

标签: angular typescript

我有一个将业务对象作为输入的组件。在此组件的模板中,我希望通过检查仅存在于业务对象的某些子类上的属性的值来有条件地呈现某些内容。

export class Thing { public foo: string; }
export class SubThing extends Thing { public bar: number; }

// ...
export class MyComponent {
  @Input() thing: Thing;
}
<!-- template file -->
{{ thing.foo }}
<div *ngIf="thing?.bar > 10">Conditional content...</div>

这曾经像写的那样工作,因为编译器对模板中的类型检查不是很严格。最近这开始打破了AOT编译器(不确定的确切时间),因为严格来说,thing?.bar在编译器认为thing只是Thing时无效,并且不能说确定它是SubThing

我想说*ngIf="thing instanceof SubThing && thing?.bar > 10"之类的内容,但我不能在模板本身中使用instanceof。还有其他方法可以从模板中检查thing的类型,以便编译器停止抱怨吗? (我通过将输入指定为any使我的构建工作再次起作用,但我当然希望在可能的情况下检查我的类型。)

2 个答案:

答案 0 :(得分:1)

显然编译器尊重User Defined Type Guards。我只需要在我的组件中定义一个方法:

export class MyComponent {
  // ...
  /** @internal */ isSubThing(t: Thing): t is SubThing {
    return t instanceof SubThing;
  }
}
<!-- template file -->
{{ thing.foo }}
<div *ngIf="isSubThing(thing) && thing?.bar > 10">
  Conditional content...
</div>

答案 1 :(得分:0)

编辑:从 Angular 11 开始,模板中的类型保护看起来工作正常。我在下面的回答可能对运行 Ivy 早期版本的人仍然有用。

Angular Ivy 有一种方法可以通过严格的模板检查在模板中进行类型缩小。这有点hacky,但它有效。您在组件中创建一个方法,如果它通过类型检查,则返回对象,如果没有,则返回 undefined。然后使用 then 将该方法的结果分配给 ngIf 表达式中的一个新变量。新变量的类型正确

export class MyComponent {
   // ...
   
   public isSubThing(t: Thing): SubThing | undefined{
       return t instanceof SubThing? t : undefined;
   }
}

<!-- template file -->
{{ thing.foo }}
<ng-container *ngIf="isSubThing(thing) as subThing">
    <div *ngIf="subThing.bar > 10">
      Conditional content...
    </div>
</ng-container>

这是一个堆栈闪电战:https://stackblitz.com/edit/angular-ivy-gmqkzj