Angular ng模板类型变量

Angular ng模板类型变量,angular,typescript,Angular,Typescript,父组件如何识别来自ngTemplateOutletContext的let内容的类型?现在{{content.type}工作正常,但IDE说: 未解析变量类型 如何将其输入为视频 parent.component.ts: export interface Video { id: number; duration: number; type: string; } public videos: Video = [{id: 1, duration: 30, type: 'documenta

父组件如何识别来自
ngTemplateOutletContext
let内容的类型?现在
{{content.type}
工作正常,但IDE说:

未解析变量类型

如何将其输入为
视频

parent.component.ts:

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

public videos: Video = [{id: 1, duration: 30, type: 'documentary'}];
<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>
@Component({
  selector: 'tile',
  templateUrl: './tile.component.html',
  styleUrls: ['./tile.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CardComponent {
  @Input() tileTemplate: TemplateRef<any>;
  @Input() content: Video;
}
<div
...
  <ng-container
    [ngTemplateOutlet]="tileTemplate"
    [ngTemplateOutletContext]="{ $implicit: content }">
  </ng-container>
...
</div>
parent.component.html:

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

public videos: Video = [{id: 1, duration: 30, type: 'documentary'}];
<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>
@Component({
  selector: 'tile',
  templateUrl: './tile.component.html',
  styleUrls: ['./tile.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CardComponent {
  @Input() tileTemplate: TemplateRef<any>;
  @Input() content: Video;
}
<div
...
  <ng-container
    [ngTemplateOutlet]="tileTemplate"
    [ngTemplateOutletContext]="{ $implicit: content }">
  </ng-container>
...
</div>
{{content.type}
tile.component.ts:

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

public videos: Video = [{id: 1, duration: 30, type: 'documentary'}];
<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>
@Component({
  selector: 'tile',
  templateUrl: './tile.component.html',
  styleUrls: ['./tile.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CardComponent {
  @Input() tileTemplate: TemplateRef<any>;
  @Input() content: Video;
}
<div
...
  <ng-container
    [ngTemplateOutlet]="tileTemplate"
    [ngTemplateOutletContext]="{ $implicit: content }">
  </ng-container>
...
</div>
@组件({
选择器:'tile',
templateUrl:'./tile.component.html',
样式URL:['./tile.component.scss'],
changeDetection:ChangeDetectionStrategy.OnPush,
})
出口级卡片组件{
@Input()tileTemplate:TemplateRef;
@输入()内容:视频;
}
tile.component.html:

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

public videos: Video = [{id: 1, duration: 30, type: 'documentary'}];
<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>
@Component({
  selector: 'tile',
  templateUrl: './tile.component.html',
  styleUrls: ['./tile.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CardComponent {
  @Input() tileTemplate: TemplateRef<any>;
  @Input() content: Video;
}
<div
...
  <ng-container
    [ngTemplateOutlet]="tileTemplate"
    [ngTemplateOutletContext]="{ $implicit: content }">
  </ng-container>
...
</div>

对于
let-*
变量没有类型推断。
let-
上下文是Angular的微语法解析器的一部分,IDE无法推断类型,因为没有明确的来源

您可以尝试使用
$any()


{{$any(content.type}}
您可以使用函数强制进行类型推断

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

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

{{toVideo(content.type}}
public-toVideo(值:any):Video{返回值为Video;}

有一个简单的解决方法,可以让IDE发挥作用,还可以使用用户定义的类型保护完成代码:

在类中创建一个函数,该函数将变量作为参数并返回相同的变量:

export class CardComponent {
  ...
  public video = (item: Video) => item;
}
现在,只需使用以下函数将变量包装到模板中:

<h5 class="tile__type">{{video(content).type}}</h5>
{{视频(内容).type}

这可以通过将变量包装到另一个
ng模板中来解决

这是另一种解决方法,但我比其他解决方案更喜欢它,因为它只是在HTML中增加了两行代码,当然,如果您只使用变量1或2次@Reactingular会更好。我的答覆是:

与此相反:

这是非类型化的:{{args.fooProp}}
这样做:

这是类型化的:{{args.fooProp}}
identity(foo:foo):foo{
返回foo;
}
类型断言是在使用
*ngFor
*ngIf
时进行的。此解决方案的缺点是,由于
[ngIf]
的原因,内部的
会在稍后渲染

现在,如果您在上下文中添加了无效属性,您将得到以下编译错误,这是非常严重的:

类型“Foo”上不存在属性“newFooProp”


我见过的最好的解决方法——使用1个字符的变量名,它几乎不会扰乱模板。但很难相信这是必要的……这是@reactogular在接受答案时给出的解决方案的重新发布:但这将导致ngZone在每次运行时调用该函数。我认为,如果你在每一个方面都有这样的缺点,那么就不值得有这样的性能缺陷template@MusabKurt是的,会的。另一种方法是使用管道,这更方便,因为可以在不同的构件模板中使用管道。我希望Angular团队能为我们介绍一种为模板定义自定义$type()方法的方法。如果您使用
changeDetection:ChangeDetectionStrategy,那么您可能不会使用这种方法。OnPush
这是否回答了您的问题?