Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I do type-narrowing in an Angular template?

I have a component that takes a business object as an Input. In the template for this component, I want to conditionally render some content by checking the value of a property that only exists on some subclasses of the business object.

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>

This used to work as written because the compiler wasn't very strict about type checking in the templates. Recently this started breaking with the AOT compiler (not sure exactly when) because, strictly speaking, thing?.bar is not valid when the compiler thinks thing is just a Thing, and can't say for certain that it's a SubThing.

I would like to say something like *ngIf="thing instanceof SubThing && thing?.bar > 10" but I can't use instanceof in the template itself. Is there some other way I can check the type of thing from the template, such that the compiler stops complaining? (I got the build working again by specifying my Input as any but of course I'd like to get my type checking back if possible.)

like image 599
Coderer Avatar asked Nov 10 '17 10:11

Coderer


People also ask

Does Angular have template type checking?

Overview of template type checkinglink. Just as TypeScript catches type errors in your code, Angular checks the expressions and bindings within the templates of your application and can report any type errors it finds.

What is type narrowing in Angular?

Type narrowing is just what it sounds like—narrowing down a general type into something more precise. If you've ever dealt with union types, e.g. string | number you've certainly encountered this.

Which of the following tags is not supported by the Angular template?

To eliminate the risk of script injection attacks, Angular does not support the <script> element in templates. Angular ignores the <script> tag and outputs a warning to the browser console.

How do you type narrow union TypeScript?

TypeScript Union Type Narrowing To narrow a variable to a specific type, implement a type guard. Use the typeof operator with the variable name and compare it with the type you expect for the variable.


1 Answers

Apparently the compiler respects User Defined Type Guards. I just have to define a method in my component:

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>
like image 115
Coderer Avatar answered Sep 23 '22 18:09

Coderer