我有一个看起来像这样的模板(我使用的是一个使用它作为重复项的基础的组件,它是p-pickList,但问题并不是特定于该组件,仅作为示例)
对于背景,假设我有一个类型Foo
,我的组件有一个foos: Foo[]
,我把它喂给<p-pickList>
属性下的[source]
组件,它为它做内部*ngFor
,我所要做的就是提供一个模板
<ng-template let-foo pTemplate="item">
...
{{ foo.anythingGoesHereWithNoWarningAndNoAutocomplete }}
但是,关于foo
的类型信息似乎丢失了。
我是类型安全的忠实粉丝,我喜欢Intellij(或任何其他编辑)可以向我显示警告,如果在模板中我做了类似指定foo
的无效属性的事情
如果我有一个常规的*ngFor
,它会推断出foo
的类型
<div *ngFor="let foo of foos">
{{ foo.autoCompleteWorksInMostIDEsAsWellAsWarningIfInvalidProp }}
let-foo
的类型? (希望大多数IDE都能识别)。foo
(由let-foo声明)?tl; dr是否有一种语法可以让我输入注释模板输入变量?例如像这样的东西组成了语法?
let-foo="$implicit as Foo"
或let-foo-type="Foo"
?
一个愚蠢的想法是在我的组件中有一个身份功能,例如
identity(foo: Foo): Foo {
return foo;
}
但是做
{{ identity(foo).fooProp }}
不是一个很大的进步
{{ (foo as Foo).fooProp }}
VSCode应该具有开箱即用的功能,只需在stackblitz:https://stackblitz.com/edit/angular-type-assertion?file=src/app/app.component.html中测试
让我们看看角度有什么相似之处以及它是如何工作的!
<p *ngFor="let number of [{v: 101},{v: 102}, {v: 103}]">{{number.v}}</p>
我们可以在没有*
魔法的情况下重写它
<ng-template ngFor let-number [ngForOf]="[{v: 101},{v: 102}, {v: 103}]">
<p>{{number.v}}</p>
</ng-template>
没有观察者(ngDoCheck),它可以与(但ngTemplateOutlet have no typecheck)相同:
<ng-template let-number #templateRef>
<p>{{number.v}}</p>
</ng-template>
<ng-container *ngTemplateOutlet="templateRef; context: {$implicit: {v: 101}}"></ng-container>
<ng-container *ngTemplateOutlet="templateRef; context: {$implicit: {v: 102}}"></ng-container>
<ng-container *ngTemplateOutlet="templateRef; context: {$implicit: {v: 103}}"></ng-container>
或者我们可以自己创造它
// template
<button (click)=create(templateRef)>create</button>
// TS
constructor(private _viewContainerRef: ViewContainerRef) {
}
create(templateRef: TemplateRef<{$implicit: {v: number;}}>) {
this._viewContainerRef.createEmbeddedView(templateRef, {$implicit: {v: 101}});
this._viewContainerRef.createEmbeddedView(templateRef, {$implicit: {v: 102}});
this._viewContainerRef.createEmbeddedView(templateRef, {$implicit: {v: 103}});
}
TL; DR
模板类型检查魔法发生在viewContainerRef.createEmbeddedView
内。 (例如ngFor);但它假设templateRef接受什么。
Angular可以在AOT中编译:
<p *ngFor="let num of [{v:1}, {v:2}]">
{{num.does.not.exist.completly}}
</p>
因此,据我所知,我们应该假设模板具有哪些类型,但确实在模板实例化时进行检查(通过createEmbeddedView
);
发现此问题并提出了允许模板输入变量发布类型信息的解决方案,以便IDE可以在github here上提供更好的完成。这个功能目前正在开发中,希望它将在未来的Angular版本中出现。您现在应该在VS Code或Sublime Text中使用Angular Language Service扩展名。你可以放心扩展的支持,因为它正在由Angular团队进行。欲了解更多信息,请查看此readme和docs。
正如您所提到的,它可以通过使用身份功能来实现,但它会导致严重的性能问题,并且对于不同类型维护此功能将是一团糟。
问题是没有任何类型信息。 <ng-template let-foo pTemplate="item">
- 只是模板声明,它还没有绑定到任何类型/上下文,只是一些具有或可能具有anythingGoesHereWithNoWarningAndNoAutocomplete
字段的动态类型。如果没有适当的仿制药支持,就不可能有这种类型的安全性。