【问题标题】:Type checking in Angular 2 templatesAngular 2 模板中的类型检查
【发布时间】:2016-02-13 14:49:37
【问题描述】:

我们正在使用 Angular 2 和 TypeScript 构建应用程序。我们尝试在可能的情况下静态检查类型。有没有办法检查模板中的类型?考虑以下片段:

<foo [data]="dataObj"></foo>

假设Foo 组件中的data 具有某种类型TData。但是,默认情况下,没有什么可以阻止我传递不符合TDatadataObj。是否有 Angular 模板的 typescript 扩展可以验证这种情况下的类型?

【问题讨论】:

  • 目前没有任何“插件”可以做到这一点(你需要打字稿)。 Angular2 确实付出了很多努力来让 IDE 可以访问他们的代码和模板,但这就是未来。
  • @gilamran 即使使用 TypeScript 我该怎么做?
  • 想了想,也许解决方案是包装函数?类似&lt;foo [data]="typeCheck(expectedtype,dataObj)&gt; &lt;/foo&gt;" 的东西,其中expectedtype 应该匹配[data] 的类型。当然,这需要程序员方面付出更多的努力,但这是我现在能想到的唯一方法。我很快就会尝试这个,如果它有效,我会发布一个答案。
  • 你不能在 Angular 2 模板表达式中使用 typeof 吗?只是一个想法
  • 我知道这不是一个真正的“解决方案”,但是当您使用 AOT 编译时,您的模板会被编译到结果文件中,然后当这些 ngfactory TS 文件被转译时,将会发现任何打字稿错误。这与 JIT 编译不同,因为使用 JIT,模板编译发生在运行时,因此不涉及 Typescript 检查。当我第一次尝试使用 AOT 运行我的项目时,我发现各种以前未报告的类型错误和从模板访问的私有变量/方法。

标签: angular typescript angular2-template


【解决方案1】:

从 Angular 9 开始,解决方案是 Angular 编译选项的 strictTemplates 标志,请参阅 Template type checking 指南的 Strict mode 部分。在tsconfig.json 文件中启用标志:

{
    ...
    "compilerOptions": { ... },
    "angularCompilerOptions": {
        "strictTemplates": true
        ...
    }
}

原答案:

不幸的是,当前的 Angular 版本似乎不检查组件输入和事件的类型。您可以使用AOT 编译并启用fullTemplateTypeCheck 角度编译器选项,该选项执行一些模板类型检查。

src/tsconfig.app.json 中启用 fullTemplateTypeCheck 选项

{
    "compilerOptions": { ... },
    "angularCompilerOptions": {
        "fullTemplateTypeCheck": true
        ...
    }
}

并使用--aot 选项构建(或服务)您的项目

ng build --aot

关于输入和事件类型检查,我在 angular bug tracker 上发现了两个问题(issue1issue2)。据我了解,问题的解决方案取决于渲染器的实现,并且更有可能在下一个版本的角度渲染器中修复该问题,称为IvyHere is ivy 渲染器中输入类型检查的功能请求。

【讨论】:

  • 但这仍然不检查组件输入,对吗?我尝试发送错误的输入,ng build --aot 没有出错
  • @UrbKr,是的,AOT 编译似乎不会强制输入类型检查。您可以在我更新的答案中找到更多详细信息。
  • 不幸的是,这也不检查从异步管道中提取的对象类型
  • 我在 tsconfig.json 中使用了 {"fullTemplateTypeCheck": true} 但毕竟它既不工作也不编译 html 模板。
【解决方案2】:

引用官方声明:

在模板类型检查阶段,Angular 模板编译器使用 TypeScript 编译器来验证模板中的绑定表达式。

当在模板绑定表达式中检测到类型错误时,模板验证会生成错误消息,类似于 TypeScript 编译器针对 .ts 文件中的代码报告类型错误的方式。

更多信息:

角度模板检查https://angular.io/guide/aot-compiler#binding-expression-validation

要激活它,您应该构建应用程序,通过

ng build --aot

ng build --prod

但您也可以在不构建的情况下激活它:

ng serve --aot

【讨论】:

    【解决方案3】:

    你可以使用管道:

    export class ObjectTypePipe implements PipeTransform {
        transform(value: any, args?: any): string {
            if (value != undefined && value != null) {
                return value.constructor.name.toString();
            }
            return "";
        }
    }
    

    这将允许您进行字符串比较。

    【讨论】:

      【解决方案4】:

      您的组件 Input() 应该具有类型。假设你有一个列表组件

      import {Component, Input, OnInit } from '@angular/core';
      
      import { Items } from '../../../services/Items';
      
      @Component({
        selector: 'my-list',
        templateUrl: './my-list.component.html',
        styleUrls: ['./my-list.component.scss'],
      })
      export class CategoryListComponent implements OnInit {
        @Input() items: Items;
      
        constructor() { }
      
        ngOnInit() { }
      }
      

      “Items”应定义为接口并导入

      export interface List {
        name: string,
        children: Items[]
      }
      
      export interface Item {
        name: string;
        slug: string;
        imageUrl: string;
        children: Item[];
      }
      

      现在你可以像这样使用它了

      <my-list [items]="items"></my-list>
      

      【讨论】:

        【解决方案5】:

        Jetbrains 的WebStorm 可以做到这一点。

        我原来的答案:

        如果不做一些事情,我认为没有可靠的方法来做到这一点 像 React 对语言的 JSX 或 TSX 扩展一样思考。

        typescript 编译器不知道你的 HTML 文件,并且会 只是忽略它们。此外,您之间没有强耦合 模板和控制器代码......没有什么能阻止你 跨多个控制器重用同一个模板。

        【讨论】:

        • 现在有AOT,考虑到模板。
        • 另外,刚刚注意到来自 Jetbrains 的 WebStorm 能够检查模板上的变量类型。
        【解决方案6】:

        如果您使用的是 Visual Studio 代码,您可以尝试使用 language service 扩展。它仍在大力开发中,您可以在测试版中考虑它。但是当我肯定会说它让我更有效率时。不仅是它的类型检查,还有 cmd + 点击组件去它们的源代码。

        如果我没记错的话,this 项目最终会在它有点稳定的时候被合并到 vscode 中,因为它符合 vscode 的最佳利益,以保持 Angular 开发人员的生产力。

        您可以放心扩展程序的支持,因为 Angular 团队正在开发它。欲了解更多信息,请查看此readme

        编辑: sublime text 和 webstorm 也支持这个。

        【讨论】:

          【解决方案7】:

          我认为 IDE 或 linter 可能会为你捕捉到这个,但如果有人真的需要这个,一个选择是创建一个 Pipe 来在运行时进行类型检查。

          @Pipe({ name: 'typeCheck' })
          export class TypeCheckPipe implements PipeTransform {
          
            transform(value: any, classType: object): any[] {
              if (value &&
                !(value instanceof classType)
              ) {
                  throw new TypeError("Input is not instanceof " + classType + 
                                      " but was " + typeof(value));
              }
              return value;
            }
          }
          

          您可以像这样在组件模板中使用它:

          <custom-component [coolInput]="coolInput | typeCheck:coolInputClass"></custom-component>
          

          我发现的唯一问题是我不确定如何将类函数注入到模板中,而不是作为组件的实例。

          @Component({
            selector: 'my-app',
            template: `
            <div>
              <custom-component [coolInput]="coolInput | typeCheck:coolInputClass"></custom-component>
            </div>
            `,
          })
          export class App {
            coolInput: CoolInput;
            coolInputClass: object = CoolInput;
          
            constructor() {
              this.coolInput = "This is the wrong type";
            }
          }
          

          这是一个 Plunker,说明了工作错误消息(通过区域抛出)。 https://plnkr.co/edit/WhoKSdoKUFvNbU3zWJy6?p=preview

          【讨论】:

          • 问题是关于静态检查而不是在运行时检查
          • 哦,我明白了。认为这是一个奇怪的要求。我相信你不能用打字稿本身做到这一点。您需要一个额外的工具来检查模板文件,因为它们不是由打字稿处理的。或许就像短绒布一样。但是,我目前不知道有什么工具可以验证 angular2 组件输入的类型。
          • Linter 不会为你捕捉到这个。
          猜你喜欢
          • 2020-05-08
          • 1970-01-01
          • 2017-10-18
          • 1970-01-01
          • 2018-02-08
          • 1970-01-01
          • 2013-10-13
          • 1970-01-01
          • 2015-10-06
          相关资源
          最近更新 更多