angular - ng-template - typet variabel


Hvordan kan foreldrekomponenten gjenkjenne typen til let-content som kommer fra ngTemplateOutletContext? Nå fungerer {{content.type}} korrekt, men IDE-en sier:

uløst variabeltype

Hvordan kan jeg skrive det som Video?

parent.component.ts:

export interface Video {
  id: number;
  duration: number;
  type: string;
}

public videos: Video = [{id: 1, duration: 30, type: 'documentary'}];

parent.component.html:

<ul>
  <li *ngFor="let video of videos">
    <tile [bodyTemplate]="tileTemplate" [content]="video"></app-card>
  </li>
</ul>

<ng-template #tileTemplate let-content>
  <h5 class="tile__type">{{content.type}}</h5>
</ng-template>

tile.component.ts:

@Component({
  selector: 'tile',
  templateUrl: './tile.component.html',
  styleUrls: ['./tile.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CardComponent {
  @Input() tileTemplate: TemplateRef<any>;
  @Input() content: Video;
}

tile.component.html:

<div
...
  <ng-container
    [ngTemplateOutlet]="tileTemplate"
    [ngTemplateOutletContext]="{ $implicit: content }">
  </ng-container>
...
</div>

Svar #1

Jeg laget en hjelpeanvisning for å løse dette.

import { Directive, Input, TemplateRef } from '@angular/core';

@Directive({selector: 'ng-template[typedTemplate]'})
export class TypedTemplateDirective<TypeToken> {

  // how you tell the directive what the type should be
  @Input('typedTemplate')
  typeToken: TypeToken;

  // the directive gets the template from Angular
  constructor(private contentTemplate: TemplateRef<TypeToken>) {
  }

  // this magic is how we tell Angular the context type for this directive, which then propagates down to the type of the template
  static ngTemplateContextGuard<TypeToken>(dir: TypedTemplateDirective<TypeToken>, ctx: unknown): ctx is TypeToken{ return true; }
}

Bruk det slik

<!-- typedTemplate is the directive, typeToken is an object on our component -->
<ng-template #someTemplate [typedTemplate]="typeToken" let-param="param">
  {{param}}
</ng-template>

Og i komponenten

// here we create typeToken. the value doesn't matter as it's never used, but the type of this variable defines the types of all template parameters. 
typeToken: { param: string };

Svar #2

Det er ingen typeinferenz for let-*-variabler. let--konteksten er en del av mikrosyntaksparseren for Angular, og et IDE kan ikke inferere typen da det ikke finnes noen klar opprinnelse.

https://gist.github.com/mhevery/d3530294cff2e4a1b3fe15ff75d08855

Du kan prøve å ignorere IDE-advarselen ved å bruke $any()

https://angular.io/guide/template-syntax#the-any-type-cast-function

<ng-template #tileTemplate let-content>
  <h5 class="tile__type">{{$any(content).type}}</h5>
</ng-template>

Du kan tvinge typeinndeling ved å bruke en funksjon

<ng-template #tileTemplate let-content>
  <h5 class="tile__type">{{toVideo(content).type}}</h5>
</ng-template>

public toVideo(value: any): Video { return value as Video; }

Relaterte artikler