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 |
||
---|---|---|
.circleci | ||
.devcontainer | ||
.github | ||
.vscode | ||
.yarn | ||
aio | ||
docs | ||
integration | ||
modules | ||
packages | ||
scripts | ||
third_party | ||
tools | ||
.bazelignore | ||
.bazelrc | ||
.clang-format | ||
.editorconfig | ||
.gitattributes | ||
.gitignore | ||
.mailmap | ||
.nvmrc | ||
.pullapprove.yml | ||
.yarnrc | ||
BUILD.bazel | ||
CHANGELOG.md | ||
CODE_OF_CONDUCT.md | ||
CONTRIBUTING.md | ||
LICENSE | ||
README.md | ||
WORKSPACE | ||
browser-providers.conf.js | ||
gulpfile.js | ||
karma-js.conf.js | ||
package.json | ||
protractor-perf.conf.js | ||
shims_for_IE.js | ||
test-events.js | ||
test-main.js | ||
tslint.json | ||
yarn.lock | ||
yarn.lock.readme.md |
README.md
Angular
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
Quickstart
Changelog
Learn about the latest improvements.
Want to help?
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our guidelines for contributing and then check out one of our issues in the hotlist: community-help.