docs: expand type-check info in update page (#33577)

PR Close #33577
This commit is contained in:
Judy Bogart 2019-11-04 10:10:56 -08:00 committed by Kara Erickson
parent 2be0a1d35b
commit 6888cb3d7a
7 changed files with 141 additions and 108 deletions

View File

@ -77,12 +77,20 @@ When `false`, disables this rewriting, requiring the rewriting to be done manual
When `true`, the compiler does not check the TypeScript version and does not report an error when an unsupported version of TypeScript is used. Not recommended, as unsupported versions of TypeScript might have undefined behavior. Default is false.
### `enableIvy`
Enables the [Ivy](guide/ivy) compilation and rendering pipeline. Default is `true`, as of version 9. In version 9, you can [opt out of Ivy](guide/ivy#opting-out-of-angular-ivy) to continue using the previous compiler, View Engine.
For library projects generated with the CLI, the `prod` configuration default is false in version 9.
### `enableResourceInlining`
When true, replaces the `templateUrl` and `styleUrls` property in all `@Component` decorators with inlined contents in `template` and `styles` properties.
When enabled, the `.js` output of `ngc` does not include any lazy-loaded template or style URLs.
For library projects generated with the CLI, the dev configuration default is true.
{@a enablelegacytemplate}
@ -118,9 +126,9 @@ would be `"index.d.ts"`.
### `fullTemplateTypeCheck`
When true (recommended), enables the [binding expression validation](guide/aot-compiler#binding-expression-validation) phase of the template compiler, which uses TypeScript to validate binding expressions.
When true (recommended), enables the [binding expression validation](guide/aot-compiler#binding-expression-validation) phase of the template compiler, which uses TypeScript to validate binding expressions. For more information, see [Template type checking](guide/template-typecheck).
Default is currently false.
Default is false, but when you use the CLI command `ng new`, it is set to true by default in the generated project's configuration.
### `generateCodeForLibraries`
@ -154,6 +162,8 @@ When true, does not emit `.ngfactory.js` and `.ngstyle.js` files. This turns off
Can be used to instruct the template compiler to produce `.metadata.json` files for distribution with an `npm` package while avoiding the production of `.ngfactory.js` and `.ngstyle.js` files that cannot be distributed to `npm`.
For library projects generated with the CLI, the dev configuration default is true.
### `strictMetadataEmit`
When true, reports an error to the `.metadata.json` file if `"skipMetadataEmit"` is `false`.
@ -170,10 +180,21 @@ If the client of a library intends to use a symbol in an annotation, the templat
This option allows detection of these errors during the build phase of
the library and is used, for example, in producing Angular libraries themselves.
For library projects generated with the CLI, the dev configuration default is true.
### `strictInjectionParameters`
When true (recommended), reports an error for a supplied parameter whose injection type cannot be determined. When false (currently the default), constructor parameters of classes marked with `@Injectable` whose type cannot be resolved produce a warning.
When you use the CLI command `ng new`, it is set to true by default in the generated project's configuration.
### `strictTemplates`
When true, enables [strict template type checking](guide/template-typecheck#strict-mode) in Angular version 9. Strict mode is only available when using [Ivy](guide/ivy).
Additional strictness flags allow you to enable and disable specific types of strict template type checking. See [troubleshooting template errors](guide/template-typecheck#troubleshooting-template-errors).
### `trace`
When true, prints extra information while compiling templates. Default is false.

View File

@ -101,7 +101,7 @@ Project-specific [TypeScript](https://www.typescriptlang.org/) configuration fil
| :--------------------- | :------------------------------------------|
| `browserslist` | Configures sharing of target browsers and Node.js versions among various front-end tools. See [Browserslist on GitHub](https://github.com/browserslist/browserslist) for more information. |
| `karma.conf.js` | Application-specific [Karma](https://karma-runner.github.io/2.0/config/configuration-file.html) configuration. |
| `tsconfig.app.json` | Application-specific [TypeScript](https://www.typescriptlang.org/) configuration, including TypeScript and Angular template compiler options. See [TypeScript Configuration](guide/typescript-configuration). |
| `tsconfig.app.json` | Application-specific [TypeScript](https://www.typescriptlang.org/) configuration, including TypeScript and Angular template compiler options. See [TypeScript Configuration](guide/typescript-configuration) and [Angular Compiler Options](guide/angular-compiler-options). |
| `tsconfig.spec.json` | [TypeScript](https://www.typescriptlang.org/) configuration for the application tests. See [TypeScript Configuration](guide/typescript-configuration). |
| `tslint.json` | Application-specific [TSLint](https://palantir.github.io/tslint/) configuration. |

View File

@ -13,7 +13,7 @@ If you're seeing errors after updating to version 9, you'll first want to rule t
To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.json` and re-start your app.
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 9 guide](guide/updating-to-version-9).
If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 9 guide](guide/updating-to-version-9). If you've opted into any of the stricter type-checking settings that are new with v9, you may also want to check out the [template type-checking guide](guide/template-typecheck).
If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.json` and review the list of expected changes below.
@ -21,40 +21,39 @@ If the errors are gone, switch back to Ivy by removing the changes to the `tscon
{@a common-changes}
### Changes You May See
- By default, `@ContentChildren` queries will only search direct child nodes in the DOM hierarchy (previously, they would search any nesting level in the DOM as long as another directive wasn't matched above it). ([details](guide/ivy-compatibility-examples#content-children-descendants))
* By default, `@ContentChildren` queries will only search direct child nodes in the DOM hierarchy (previously, they would search any nesting level in the DOM as long as another directive wasn't matched above it). ([details](guide/ivy-compatibility-examples#content-children-descendants))
- All classes that use Angular DI must have an Angular decorator like `@Directive()` or `@Injectable` (previously, undecorated classes were allowed if an ancestor class or subclass had a decorator).
- Unbound inputs for directives (e.g. name in `<my-comp name="">`) are now set upon creation of the view, before change detection runs (previously, all inputs were set during change detection).
* All classes that use Angular DI must have an Angular decorator like `@Directive()` or `@Injectable` (previously, undecorated classes were allowed if an ancestor class or subclass had a decorator).
* Unbound inputs for directives (e.g. name in `<my-comp name="">`) are now set upon creation of the view, before change detection runs (previously, all inputs were set during change detection).
{@a less-common-changes}
### Less Common Changes
### Less Common Changes
- Properties like `host` inside `@Component` and `@Directive` decorators can be inherited (previously, only properties with explicit field decorators like `@HostBinding` would be inherited).
* Properties like `host` inside `@Component` and `@Directive` decorators can be inherited (previously, only properties with explicit field decorators like `@HostBinding` would be inherited).
- HammerJS support is opt-in through importing the `HammerModule` (previously, it was always included in production bundles regardless of whether the app used HammerJS).
* HammerJS support is opt-in through importing the `HammerModule` (previously, it was always included in production bundles regardless of whether the app used HammerJS).
- `@ContentChild` and `@ContentChildren` queries will no longer be able to match their directive's own host node (previously, these queries would match the host node in addition to its content children).
* `@ContentChild` and `@ContentChildren` queries will no longer be able to match their directive's own host node (previously, these queries would match the host node in addition to its content children).
- If a token is injected with the `@Host` or `@Self` flag, the module injector is not searched for that token (previously, tokens marked with these flags would still search at the module level).
* If a token is injected with the `@Host` or `@Self` flag, the module injector is not searched for that token (previously, tokens marked with these flags would still search at the module level).
- When accessing multiple local refs with the same name in template bindings, the first is matched (previously, the last instance was matched).
* When accessing multiple local refs with the same name in template bindings, the first is matched (previously, the last instance was matched).
- Directives that are used in an exported module (but not exported themselves) are exported publicly (previously, the compiler would automatically write a private, aliased export that it could use its global knowledge to resolve downstream).
* Directives that are used in an exported module (but not exported themselves) are exported publicly (previously, the compiler would automatically write a private, aliased export that it could use its global knowledge to resolve downstream).
- Foreign functions or foreign constants in decorator metadata aren't statically resolvable (previously, you could import a constant or function from another compilation unit, like a library, and use that constant/function in your `@NgModule` definition).
* Foreign functions or foreign constants in decorator metadata aren't statically resolvable (previously, you could import a constant or function from another compilation unit, like a library, and use that constant/function in your `@NgModule` definition).
- Forward references to directive inputs accessed through local refs are no longer supported by default.
* Forward references to directive inputs accessed through local refs are no longer supported by default.
- If there is both an unbound class attribute and a `[class]` binding, the classes in the unbound attribute will also be added (previously, the class binding would overwrite classes in the unbound attribute).
* If there is both an unbound class attribute and a `[class]` binding, the classes in the unbound attribute will also be added (previously, the class binding would overwrite classes in the unbound attribute).
- It is now an error to assign values to template-only variables like `item` in `ngFor="let item of items"` (previously, the compiler would ignore these assignments).
* It is now an error to assign values to template-only variables like `item` in `ngFor="let item of items"` (previously, the compiler would ignore these assignments).
- It's no longer possible to overwrite lifecycle hooks with mocks on directive instances for testing (instead, modify the lifecycle hook on the directive type itself).
* It's no longer possible to overwrite lifecycle hooks with mocks on directive instances for testing (instead, modify the lifecycle hook on the directive type itself).
- Special injection tokens (e.g. `TemplateRef` or `ViewContainerRef`) return a new instance whenever they are requested (previously, instances of special tokens were shared if requested on the same node). This primarily affects tests that do identity comparison of these objects.
* Special injection tokens (such as `TemplateRef` or `ViewContainerRef`) return a new instance whenever they are requested (previously, instances of special tokens were shared if requested on the same node). This primarily affects tests that do identity comparison of these objects.
- ICU parsing happens at runtime, so only text, HTML tags and text bindings are allowed inside ICU cases (previously, directives were also permitted inside ICUs).
* ICU parsing happens at runtime, so only text, HTML tags and text bindings are allowed inside ICU cases (previously, directives were also permitted inside ICUs).
- Providers formatted as `{provide: X}` without a `useValue`, `useFactory`, `useExisting`, or `useClass` property are treated like `{provide: X, useClass: X}` (previously, it defaulted to `{provide: X, useValue: undefined}`).
* Providers formatted as `{provide: X}` without a `useValue`, `useFactory`, `useExisting`, or `useClass` property are treated like `{provide: X, useClass: X}` (previously, it defaulted to `{provide: X, useValue: undefined}`).

View File

@ -119,7 +119,7 @@ To revert the compiler default, set the build option `aot: false` in the `angula
</div>
{@a using-ssr-without-angular-ivy}
## Using SSR without Ivy
### Using SSR without Ivy
If you opt out of Ivy and your application uses [Angular Universal](guide/universal) to render Angular applications on the server, you must also change the way the server performs bootstrapping.

View File

@ -1,41 +1,47 @@
# Template type-checking
# Template type checking
## Overview of template type-checking
## Overview of template type checking
Just as TypeScript catches type errors in your code, Angular checks the expressions and bindings within the templates of your application and can report any type errors it finds. Angular currently has three modes of doing this, depending on the value of the `fullTemplateTypeCheck` and `strictTemplates` flags.
Just as TypeScript catches type errors in your code, Angular checks the expressions and bindings within the templates of your application and can report any type errors it finds.
Angular currently has three modes of doing this, depending on the value of the `fullTemplateTypeCheck` and `strictTemplates` flags in the [TypeScript configuration file](guide/typescript-configuration), `tsconfig.json`.
### Basic mode
In the most basic type-checking mode, with the `fullTemplateTypeCheck` flag set to `false`, Angular will only validate top-level expressions in a template.
In the most basic type-checking mode, with the `fullTemplateTypeCheck` flag set to `false`, Angular validates only top-level expressions in a template.
If you write `<map [city]="user.address.city">`, the compiler will verify the following:
If you write `<map [city]="user.address.city">`, the compiler verifies the following:
* `user` is a property on the component class.
* `user` is an object with an address property.
* `user.address` is an object with a city property.
The compiler will not verify that the value of `user.address.city` is assignable to the city input of the `<map>` component.
The compiler does not verify that the value of `user.address.city` is assignable to the city input of the `<map>` component.
The compiler also has some major limitations in this mode:
* Importantly, it won't check embedded views, such as `*ngIf`, `*ngFor`, other `<ng-template>` embedded view.
* It won't figure out the types of `#refs`, the results of pipes, the type of `$event` in event bindings, etc.
* In many cases, these things end up as type `any` which can cause subsequent parts of the expression to go unchecked.
* Importantly, it doesn't check embedded views, such as `*ngIf`, `*ngFor`, other `<ng-template>` embedded view.
* It doesn't figure out the types of `#refs`, the results of pipes, the type of `$event` in event bindings, and so on.
In many cases, these things end up as type `any`, which can cause subsequent parts of the expression to go unchecked.
### Full mode
If the `fullTemplateTypeCheck` flag is set to `true`, Angular will be more aggressive in its type-checking within templates.
If the `fullTemplateTypeCheck` flag is set to `true`, Angular is more aggressive in its type-checking within templates.
In particular:
* Embedded views (such as those within an `*ngIf` or `*ngFor`) will be checked.
* Pipes will have the correct return type.
* Local references to directives and pipes will have the correct type (except for any generic parameters, which will be `any`).
* Local references to DOM elements will still have type `any`.
* `$event` will still have type `any`.
* Safe navigation expressions will still have type `any`.
* Embedded views (such as those within an `*ngIf` or `*ngFor`) are checked.
* Pipes have the correct return type.
* Local references to directives and pipes have the correct type (except for any generic parameters, which will be `any`).
The following still have type `any`.
* Local references to DOM elements.
* The `$event` object.
* Safe navigation expressions.
{@a strict-mode}
### Strict mode
@ -56,7 +62,7 @@ In addition to the full mode behavior, Angular version 9:
## Checking of `*ngFor`
The three modes of type-checking treat embedded views differently. Consider the following example:
The three modes of type-checking treat embedded views differently. Consider the following example.
<code-example language="ts" header="User interface">
@ -81,27 +87,28 @@ interface User {
The `<h2>` and the `<span>` are in the `*ngFor` embedded view.
In basic mode, Angular doesn't check either of them.
However, in full mode, Angular checks that `config` and `user` exists and assumes a type of `any`.
In strict mode, Angular knows that the `user` in the `<span>` has a type of `User` as well as `address` is an object with a `city` property of type `string`.
However, in full mode, Angular checks that `config` and `user` exist and assumes a type of `any`.
In strict mode, Angular knows that the `user` in the `<span>` has a type of `User`, and that `address` is an object with a `city` property of type `string`.
{@a troubleshooting-template-errors}
## Troubleshooting template errors
When enabling the new strict mode in version 9, you might encounter template errors which didn't arise in either of the previous modes. These errors often represent genuine type mismatches in the templates which were not caught by the previous tooling. If this is the case, the error message should make it clear where in the template the problem occurs.
When enabling the new strict mode in version 9, you might encounter template errors that didn't arise in either of the previous modes.
These errors often represent genuine type mismatches in the templates that were not caught by the previous tooling.
If this is the case, the error message should make it clear where in the template the problem occurs.
They can also be false positives when the typings of an Angular library are either incomplete or incorrect, or when the typings don't quite line up with expectations as in the following:
There can also be false positives when the typings of an Angular library are either incomplete or incorrect, or when the typings don't quite line up with expectations as in the following cases.
1. When a library's typings are wrong or incomplete (for example, missing `null | undefined` if the library was not written with `strictNullChecks` in mind).
1. When a library's input types are too narrow and the library hasn't added appropriate metadata for Angular to figure this out. This usually occurs with disabled or other common boolean inputs used as attributes, for example, `<input disabled>`.
1. When using `$event.target` for DOM events (because of the possibility of event bubbling, `$event.target` in the DOM typings doesn't have the type you might expect).
It's also possible that an error can be the result of a bug in the template type-checker itself.
* When a library's typings are wrong or incomplete (for example, missing `null | undefined` if the library was not written with `strictNullChecks` in mind).
* When a library's input types are too narrow and the library hasn't added appropriate metadata for Angular to figure this out. This usually occurs with disabled or other common Boolean inputs used as attributes, for example, `<input disabled>`.
* When using `$event.target` for DOM events (because of the possibility of event bubbling, `$event.target` in the DOM typings doesn't have the type you might expect).
In case of a false positive like these, there are a few options:
* `$any()` can be used in certain contexts to opt out of type-checking for a part of the expression.
* `strictTemplates` can be disabled entirely.
* Certain type-checking operations can be disabled individually, while maintaining strictness in other aspects, by setting a _strictness flag_ to `false`.
* Use the [`$any()` type-cast function](guide/template-syntax#any-type-cast-function) in certain contexts to opt out of type-checking for a part of the expression.
* You can disable strict checks entirely by setting `strictTemplates: false` in the application's TypeScript configuration file, `tsconfig.json`.
* You can disable certain type-checking operations individually, while maintaining strictness in other aspects, by setting a _strictness flag_ to `false`.
|Strictness flag|Effect|
|-|-|
@ -116,4 +123,8 @@ In case of a false positive like these, there are a few options:
If you still have issues after troubleshooting with these flags, you can fall back to full mode by disabling `strictTemplates`.
If that doesn't work, an option of last resort is to turn off full mode entirely with `fullTemplateTypeCheck: false`, as we've made a special effort to make Angular version 9 backwards compatible in this case. If you get errors that require falling back to basic mode, then please [file an issue](https://github.com/angular/angular/issues) so the team can address it, as it is almost definitely a bug.
If that doesn't work, an option of last resort is to turn off full mode entirely with `fullTemplateTypeCheck: false`, as we've made a special effort to make Angular version 9 backwards compatible in this case.
A type-checking error that you cannot resolve with any of the recommended methods can be the result of a bug in the template type-checker itself.
If you get errors that require falling back to basic mode, it is likely to be such a bug.
If this happens, please [file an issue](https://github.com/angular/angular/issues) so the team can address it.

View File

@ -3,8 +3,8 @@
TypeScript is a primary language for Angular application development.
It is a superset of JavaScript with design-time support for type safety and tooling.
Browsers can't execute TypeScript directly. Typescript must be "transpiled" into JavaScript using the *tsc* compiler,
which requires some configuration.
Browsers can't execute TypeScript directly.
Typescript must be "transpiled" into JavaScript using the *tsc* compiler, which requires some configuration.
This page covers some aspects of TypeScript configuration and the TypeScript environment
that are important to Angular developers, including details about the following files:
@ -15,11 +15,11 @@ that are important to Angular developers, including details about the following
{@a tsconfig}
## TypeScript configuration
## *tsconfig.json*
Typically, you add a TypeScript configuration file called `tsconfig.json` to your project to
guide the compiler as it generates JavaScript files.
A TypeScript configuration file called `tsconfig.json` guides the compiler as it generates JavaScript files for a project.
This file contains options and flags that are essential for Angular applications.
Typically, the file is found at the [root level of the workspace](guide/file-structure).
<div class="alert is-helpful">
@ -28,38 +28,38 @@ For details about `tsconfig.json`, see the official
</div>
The initial `tsconfig.json` for an Angular app typically looks like this example:
The initial `tsconfig.json` for an Angular app typically looks like the following example.
<code-example lang="json" header="tsconfig.json" linenums="false">
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"module": "es2015",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
}
}
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
}
</code-example>
This file contains options and flags that are essential for Angular applications.
{@a noImplicitAny}
@ -90,9 +90,15 @@ You can suppress them with the following additional flag:
</code-example>
<div class="alert is-helpful">
For more information about how the TypeScript configuration affects compilation, see [Angular Compiler Options](guide/angular-compiler-options) and [Template Type Checking](guide/template-typecheck).
</div>
{@a typings}
## TypeScript Typings
## TypeScript typings
Many JavaScript libraries, such as jQuery, the Jasmine testing library, and Angular,
extend the JavaScript environment with features and syntax
@ -107,8 +113,12 @@ Many libraries include definition files in their npm packages where both the Typ
can find them. Angular is one such library.
The `node_modules/@angular/core/` folder of any Angular application contains several `d.ts` files that describe parts of Angular.
**You don't need to do anything to get *typings* files for library packages that include `d.ts` files.
Angular packages include them already.**
<div class="alert is-helpful">
You don't need to do anything to get *typings* files for library packages that include `d.ts` files.
Angular packages include them already.
</div>
### lib.d.ts

View File

@ -19,9 +19,8 @@ In order to improve the updating experience, we strongly suggest that you update
Additionally, during the RC period, the `--next` command line flag is required. This flag will no longer be necessary once version 9 final is released.
</div>
The script will run a series of small migrations that will transform the code of your application to be compatible with version 9.
If you're curious about the specific migrations being run (e.g. what code is changing and why), see the [automated migrations section](#migrations).
The script runs a series of small migrations that will transform the code of your application to be compatible with version 9.
If you're curious about the specific migrations being run, see the [automated migrations section](#migrations) for details on what code is changing and why.
## Changes and Deprecations in Version 9
@ -30,14 +29,13 @@ If you're curious about the specific migrations being run (e.g. what code is cha
- Angular now compiles with Ivy by default. See [Ivy compatibility section](#ivy).
- CLI apps compile in [AOT mode](/guide/aot-compiler) by default (which includes template type-checking).
Users who only built with JIT before may see new type errors.
- CLI apps compile in [AOT mode](/guide/aot-compiler) by default (which includes template type-checking).
Users who only built with JIT before may see new type errors.
See our [template type-checking guide](guide/template-typecheck) for more information and debugging tips.
- Typescript 3.4 and 3.5 are no longer supported. Please update to Typescript 3.6.
- tslib is now listed as a peer dependency rather than a direct dependency.
Users not using the CLI will need to manually install tslib via `yarn add tslib` or `npm install tslib --save`.
- `tslib` is now listed as a peer dependency rather than a direct dependency. If you are not using the CLI, you must manually install `tslib`, using `yarn add tslib` or `npm install tslib --save`.
{@a deprecations}
### New Deprecations
@ -68,23 +66,17 @@ Users not using the CLI will need to manually install tslib via `yarn add tslib`
| `@angular/forms` | `ngForm` element selector | `ng-form` element selector | none |
| `@angular/service-worker` | `versionedFiles` | `files` | In the service worker configuration file `ngsw-config.json`, replace `versionedFiles` with `files`. See [Service Worker Configuration](guide/service-worker-config#assetgroups). |
{@a ivy-features}
## Ivy Features
Angular version 9 introduces more comprehensive type-checking. For details, see [Template Type-checking](guide/template-typecheck).
{@a ivy}
## Ivy Compatibility
## Ivy features and compatibility
In Version 9, Angular Ivy is the default rendering engine. If you haven't heard of Ivy, you can read more about it in the [Angular Ivy guide](guide/ivy).
For guidance on debugging and a list of minor changes associated with Ivy, please see our [compatibility guide](guide/ivy-compatibility).
* Among other features, Ivy introduces more comprehensive type-checking within templates. For details, see [Template Type-checking](guide/template-typecheck).
For help with opting out of Ivy, please see the instructions [here](guide/ivy#opting-out-of-angular-ivy).
* For general guidance on debugging and a list of minor changes associated with Ivy, see the [Ivy compatibility guide](guide/ivy-compatibility).
* For help with opting out of Ivy, see the instructions [here](guide/ivy#opting-out-of-angular-ivy).
{@a migrations}
## Automated Migrations for Version 9