a61fe4177f
In its default compatibility mode, the Ivy template type-checker attempts to emulate the View Engine default mode as accurately as is possible. This commit addresses a gap in this compatibility that stems from a View Engine type-checking bug. Consider two template expressions: ```html {{ obj?.field }} {{ fn()?.field }} ``` and suppose that the type of `obj` and `fn()` are the same - both return either `null` or an object with a `field` property. Under View Engine, these type-check differently. The `obj` case will catch if the object type (when not null) does not have a `field` property, while the `fn()` case will not. This is due to how View Engine represents safe navigations: ```typescript // for the 'obj' case (obj == null ? null as any : obj.field) // for the 'fn()' case let tmp: any; ((tmp = fn()) == null ? null as any : tmp.field) ``` Because View Engine uses the same code generation backend as it does to produce the runtime code for this expression, it uses a ternary for safe navigation, with a temporary variable to avoid invoking 'fn()' twice. The type of this temporary variable is 'any', however, which causes the `tmp.field` check to be meaningless. Previously, the Ivy template type-checker in compatibility mode assumed that `fn()?.field` would always check for the presence of 'field' on the non-null result of `fn()`. This commit emulates the View Engine bug in Ivy's compatibility mode, so an 'any' type will be inferred under the same conditions. As part of this fix, a new format for safe navigation operations in template type-checking code is introduced. This is based on the realization that ternary based narrowing is unnecessary. For the `fn()` case in strict mode, Ivy now generates: ```typescript (null as any ? fn()!.field : undefined) ``` This effectively uses the ternary operator as a type "or" operation. The resulting type will be a union of the type of `fn()!.field` with `undefined`. For the `fn()` case in compatibility mode, Ivy now emulates the bug with: ```typescript (fn() as any).field ``` The cast expression includes the call to `fn()` and allows it to be checked while still returning a type of `any` from the expression. For the `obj` case in compatibility mode, Ivy now generates: ```typescript (obj!.field as any) ``` This cast expression still returns `any` for its type, but will check for the existence of `field` on the type of `obj!`. PR Close #35462 |
||
---|---|---|
.. | ||
animations | ||
bazel | ||
benchpress | ||
common | ||
compiler | ||
compiler-cli | ||
core | ||
docs | ||
elements | ||
examples | ||
forms | ||
http | ||
language-service | ||
localize | ||
platform-browser | ||
platform-browser-dynamic | ||
platform-server | ||
platform-webworker | ||
platform-webworker-dynamic | ||
private/testing | ||
router | ||
service-worker | ||
upgrade | ||
zone.js | ||
BUILD.bazel | ||
README.md | ||
empty.ts | ||
goog.d.ts | ||
license-banner.txt | ||
system.d.ts | ||
tsconfig-build-no-strict.json | ||
tsconfig-build.json | ||
tsconfig-test.json | ||
tsconfig.json | ||
types.d.ts |
README.md
Angular
The sources for this package are in the main Angular repo. Please file issues and pull requests against that repo.
Usage information and reference details can be found in Angular documentation.
License: MIT