Repository navigation
Description
🚀 feature request
Relevant Package
@angular/compiler
Description
Optional chaining[1] reached stage 4. We've been supporting similar syntax in templates for a while now, calling it the "safe navigation operator"[2]. For simplicity and smaller payload, we can consider aligning with the spec in future versions of the framework.
There are a couple of semantical and syntactical differences between optional chaining and safe navigation.
Syntax
Optional chaining has the following syntax:
obj?.prop // optional static property access
obj?.[expr] // optional dynamic property access
func?.(...args) // optional function or method callSafe navigation supports only direct property access. Optional chaining supports this, as well as, method calls and function calls. Function calls are particularly useful in iterators:
iterator.return?.()Semantics
With optional chaining, the expression a?.b will be translated to a == null ? undefined : a.b. In Angular, the semantics of the same expression would be null == a ? null : a.b.
If a is null or undefined, the expression typeof a?.b would evaluate to "object" with optional chaining and "undefined" in Angular's safe navigation operator.
Except the mentioned difference above, method calls are compiled similarly:
a?.b()
a == null ? undefined : a.b()In both, optional chaining and safe navigation in templates, stacking the operators is translated the same way: (a?.b).c?.d becomes null == a ? null : null == a.b.c ? null : a.b.c.d.
Another difference seems to be the way parentheses are handled. The optional chaining spec defines that null==e.foo?null:e.foo.b.c should be translated to (a == null ? undefined : a.b).c. In Angular the same expression translates to null == a ? null : a.b.c.
PS: looks like the last issue is fixed by #34221.
[1] Optional chaining spec https://github.com/tc39/proposal-optional-chaining
[2] Safe navigation https://angular.io/guide/template-syntax#safe-navigation-operator
Activity
thw0rted commentedon Feb 24, 2020
Just to check, does this cover the case of array-index optional chaining (
arr?.[0]) in templates? I get an error when I try to use that today, though I'm not sure if it's a problem Angular itself or just the language service.rodolfojnn commentedon Apr 2, 2020
It would be very interesting to use optional chaining in arrays, following the TS spec:
In Angular Templates, arr?.[0] causes a:
zone-evergreen.js:659 Unhandled Promise rejection: Template parse errors:
Parser Error: Unexpected token [, expected identifier or keyword at column 4 in [arr?.[0]] in ng:///ProdutoCadComponent/template.html@996:64
craftmaster2190 commentedon May 8, 2020
Arrays/Indexes are safely navigated in templates but not in the way one would expect:
In TypeScript:
foo?.bar?.[0]?.quxxIn Angular Templates:
foo?.bar[0]?.quxxSee #13254
and f31c947
craftmaster2190 commentedon May 8, 2020
TL;DR: Angular Templates resolves to
nullin safe navigation and TypeScript resolves toundefinedin optional chaining.Consider the following:
Component Typescript
Example A HTML
Example B HTML
In Example A, the loading div does not show because Angular Templates evaluates the safe-navigation to null.
In Example B, the loading div does show because TypeScript evaluates the optional chaining to undefined.
If undefined means "Loading", null means "Not set by user" and anything else is "a user-set value"; then angular's safe navigation introduces a bug in our code.
This can be even more confusing given that
preferencesisundefinedand the Angular's safe navigation resolvespreferences?.emailtonull.johnwest80 commentedon Jun 1, 2020
The problem with angular's syntax is that there's no way to check that the array isn't undefined or null. Yes, what you show will check to see if the array has that indexed item, but if I want to know that the property is in fact initialized, I have to do
foo?.bar && foo?.bar[0]?It would be much better to use optional chaining and just use
foo?.bar?.[0]?ajafff commentedon Jun 17, 2020
Another thing to note: since TypeScript 3.9 non-null-assertions don't end the optional chain
Sampath-Lokuge commentedon Sep 28, 2020
Hi,
For me it shows this:
SOF Link: https://stackoverflow.com/questions/64104994/optional-chaining-is-not-working-cannot-read-property-0-of-undefined
adeel55 commentedon Dec 26, 2020
In my case
this.property?.UserProperties?.[0].idDisplay error:
Template parse errors:
Parser Error: Unexpected token [, expected identifier or keyword at column 32 in [this.property?.UserProperties?.[0].id] in bmp.component.html@219:84
snebjorn commentedon Jun 2, 2021
bar[0]?.quxxmay be safely navigated runtime. But compile time it's not.Both the language service and the compiler errors on the above.
This makes the "safe navigated in templates" irrelevant as the compiler/type checker doesn't allow it.
The proper ES syntax (
bar?.[0]?.quxx) also makes it clear what object can benull|undefined.In the above example both
barandbar[0]can benull|undefined.36 remaining items
feat(compiler): Angular expressions with optional chaining returns `u…
feat(compiler): Angular expressions with optional chaining returns `u…
feat(compiler): Angular expressions with optional chaining returns `u…
feat(compiler): Angular expressions with optional chaining returns `u…
feat(compiler): Angular expressions with optional chaining returns `u…
feat(compiler): Angular expressions with optional chaining returns `u…
feat(compiler): Angular expressions with optional chaining returns `u…
feat(compiler): Angular expressions with optional chaining returns `u…
feat(compiler): Angular expressions with optional chaining returns `u…
feat(compiler): Angular expressions with optional chaining returns `u…
feat(compiler): Angular expressions with optional chaining returns `u…
feat(compiler): Angular expressions with optional chaining returns `u…
angular-automatic-lock-bot commentedon May 29, 2026
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.