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; }
