代码之家  ›  专栏  ›  技术社区  ›  Eran Medan

有没有办法向模板输入变量添加类型断言/注释?

  •  19
  • Eran Medan  · 技术社区  · 6 年前

    背景

    我有一个类似这样的模板(我正在使用一个组件,该组件将此作为重复项的基础,它是p-pickList,但问题并不是关于该组件的具体问题,只是作为一个示例)

    Foo 我的组件有一个 foos: Foo[] ,我把它喂给 <p-pickList> [source] 属性及其内部作用 *ngFor 为此,我所要做的就是提供一个模板

     <ng-template let-foo pTemplate="item">
       ...
       {{ foo.anythingGoesHereWithNoWarningAndNoAutocomplete }}
    

    但是,上的类型信息 foo 好像迷路了。

    我是类型安全的超级粉丝,我喜欢Intellij(或任何其他编辑器)可以在模板中显示警告,如果我在模板中指定了一个无效的属性

    如果我有一个固定的 *ngFor公司 ,它将推断出

    <div *ngFor="let foo of foos">
      {{ foo.autoCompleteWorksInMostIDEsAsWellAsWarningIfInvalidProp }}
    

    问题:

    1. let-foo ? (希望大多数ide都能认识到)。

    2. (由let foo声明)?

    太长了,读不下去了,有没有语法让我输入模板输入变量? e、 像这样的东西是编造出来的吗?

    let-foo="$implicit as Foo" let-foo-type="Foo" ?

    变通办法

    identity(foo: Foo): Foo {
      return foo;
    }
    

    但是做

    {{ identity(foo).fooProp }}

    {{ (foo as Foo).fooProp }}

    5 回复  |  直到 6 年前
        1
  •  1
  •   hamilton.lima    6 年前

    VSCode应该具有开箱即用的特性,刚刚在stackblitz中测试过: https://stackblitz.com/edit/angular-type-assertion?file=src/app/app.component.html

    enter image description here

        2
  •  2
  •   Buggy    6 年前

    让我们看看angular有什么相似的tho和它是如何工作的!

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

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

    模板类型检查魔术发生在里面 viewContainerRef.createEmbeddedView . (例如 ngFor 但它假设templateRef接受什么。

    Angular可以在AOT中编译:

    <p *ngFor="let num of [{v:1}, {v:2}]">
      {{num.does.not.exist.completly}}
    </p>
    

    createEmbeddedView );

        3
  •  2
  •   kemsky    6 年前

    <ng-template let-foo pTemplate="item"> -只是一个模板声明,它还没有绑定到任何类型/上下文,只是一些具有或可能具有 anythingGoesHereWithNoWarningAndNoAutocomplete 现场。没有适当的泛型支持,就不可能有这种类型安全性。

        4
  •  2
  •   Abdul Rafay    6 年前

    发现了这个问题并提出了允许模板输入变量发布类型信息的解决方案,这样ide就可以在github上提供更好的完成 here Angular Language Service 扩展在VS代码或崇高的文本现在。你可以放心扩展的支持,因为它是由Angular团队工作。有关更多信息,请查看此 readme docs .

    正如您所提到的,它可以通过使用identity函数来实现,但是它会导致严重的性能问题,并且为不同的类型维护此功能会很麻烦。

        5
  •  1
  •   ForestG    6 年前

    使用接口可以实现您提到的行为:

    export interface Dog {
      name: string;
      age: number;
    }
    

    在组件中定义变量:

    @Component()...{
    ...
      mrSnuggles: Dog = {
        name: 'mrSnuggles',
        age: 10
      };
    }
    

    在模板中:

      {{mrSnuggles.food}}
    

    您可以看到错误(intellij idea):

    enter image description here