Type checking in Angular 2 templates

后端 未结 7 514
夕颜
夕颜 2021-02-02 06:07

We are building an application in Angular 2 and TypeScript. We try to statically check types where it is possible. Is there any way to check types in templates? Consider the fol

相关标签:
7条回答
  • 2021-02-02 06:18

    I think an IDE or linter might catch this for you, but if someone really needs this, one option would be to create a Pipe to do the type checking at run time.

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

    You can use it in a component template like this:

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

    The only catch I found is that I'm not sure how to inject the class function into the template other than as an instance of the 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";
      }
    }
    

    Here is a Plunker illustrating the working error message (thrown via Zone). https://plnkr.co/edit/WhoKSdoKUFvNbU3zWJy6?p=preview

    0 讨论(0)
  • 2021-02-02 06:19

    You could use a Pipe:

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

    This would then allow you to do a string comparison.

    0 讨论(0)
  • 2021-02-02 06:21

    WebStorm from Jetbrains can do that.

    My original answer:

    I don't think there's a reliable way to do that without doing some think like React does with the JSX or TSX extension to the language.

    The typescript compiler doesn't know about your HTML files, and will just ignore them. Also, there's no strong coupling between your templates and the Controller code... there's nothing preventing you from reusing the same template across several controllers.

    0 讨论(0)
  • 2021-02-02 06:22

    to quote the official statement:

    In the template type-checking phase, the Angular template compiler uses the TypeScript compiler to validate the binding expressions in templates.

    Template validation produces error messages when a type error is detected in a template binding expression, similar to how type errors are reported by the TypeScript compiler against code in a .ts file.

    More at:

    Angular Template checking https://angular.io/guide/aot-compiler#binding-expression-validation

    Yet to activate it, you should build the app, by

    ng build --aot
    

    or

    ng build --prod

    but you can also activate it without building:

    ng serve --aot

    0 讨论(0)
  • 2021-02-02 06:26

    If you are using visual studio code, you could try out the language service extension. Its still under heavy development, and you could consider it in beta. But when I would definitely say that it have made me more productive. Not only its type checking, but also cmd + clicking components to go to their source.

    If I am not mistaken, this project will eventually be merged to vscode it self when its somewhat stable as its in vscode's best interest to keep angular developers productive.

    You can rest assured about the extension's support because it's being worked on by the angular team. For more information checkout this readme

    Edit: sublime text and webstorm support this too.

    0 讨论(0)
  • 2021-02-02 06:29

    Since Angular 9 the solution is strictTemplates flag of Angular compile options, see Strict mode section of Template type checking guide. Enable the flag in tsconfig.json file:

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

    Original answer:

    Unfortunately, It seems that current Angular version doesn't check types of component inputs and events. You can use AOT compilation and enable fullTemplateTypeCheck angular compiler option, which performs some template type checking.

    Enable fullTemplateTypeCheck option in src/tsconfig.app.json

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

    And build (or serve) your project with --aot option

    ng build --aot
    

    What about inputs and events type checking, I found two issues on angular bug tracker (issue1 and issue2). As I understand, the solution of the problem depends on renderer implementation, and more likely that the problem may be fixed in next version of angular renderer, called Ivy. Here is feature request for inputs type checking in ivy renderer.

    0 讨论(0)
提交回复
热议问题