Home > Software design >  Bind union of types (A | B) to property of type (A) in Angular
Bind union of types (A | B) to property of type (A) in Angular

Time:12-14

I have a tree structure that contains Node<Item | Category>

type Item {
    type: string; // DB discriminator that defaults to 'I'
    id: string;
    name: string;
    text: string[];
}
type Category {
    type: string; // DB discriminator that defaults to 'C'
    id: string;
    name: string;
    sub: Category[];
}
interface Node<Item | Category> {
    data: Item | Category;
}

Then there are 2 components CategoryAndItemTreeComponent and ItemDetailsComponent.

@Component({ selector: 'app-tree', ... })
export class CategoryAndItemTreeComponent ... {
    selected?: Node<Item | Category> = null;
    ...
}

@Component({ selector: 'app-item', ... })
export class ItemDetailsComponent ... {
    item?: Item;
    ...
}

I'd like to bind details field to selected field in html:

<app-tree #treeLink></app-tree>
<app-item [item]="treeLink.selected?.data"></app-item>

...but item field is of type Item, and treeLink.selected?.data is an union of Item | Category.

How do I check instance, cast and assign?

Is this not allowed in Angular or generally in TypeScript? Apparently this compiles (inside .ts file), but not in template.

this.item = <Item>selected;

CodePudding user response:

in order to add type casting inside the template, use a custom pipe that creates the cast for you

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'customCast',
  pure: true,
})
export class AsPipe implements PipeTransform {

 transform<T, S extends T>(value: S): T {
     return <T>value;
 }

}

then you can use it in you template

treeLink.selected?.data | customCast Item
  • Related