Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decide how to reconcile async pipe with strict template type checking #33704

Closed
mmalerba opened this issue Nov 8, 2019 · 8 comments
Closed
Assignees
Labels
area: common Issues related to APIs in the @angular/common package

Comments

@mmalerba
Copy link
Contributor

mmalerba commented Nov 8, 2019

🚀 feature request

Relevant Package

This feature request is for @angular/common

Description

Currently the async pipe is difficult to use with strictTemplates and strictNullChecks enabled. This is because the async pipe emits null if the underlying observable has not emitted yet. Therefore using the async pipe with an input that does not accept null will result in a compilation error.

@devversion has done a more detailed write-up of this issue. I'm including a summary of the possible solutions here, but please refer to the write-up for more details.

Describe the solution you'd like

The ideal solution would be to make async pipe not emit until the underlying observable emits, however this would likely be a fairly breaking change. It would probably need to be done in a phased manner, while introducing something like asyncEager that maintains the old behavior to make migration easier.

Describe alternatives you've considered

  1. An option that would split the responsibility for fixing between framework and libraries is to introduce something like @RequiredInput(fallbackValue) that automatically replaces null with fallbackValue. Libraries could then update their inputs to use @RequiredInput when null is not expected.

  2. Another option that would place the responsibility on libraries is to ask them to just handle null and allow it to be passed in the template even if its not part of the input's official type (using static ngAcceptInputType_*)

  3. Finally, a third alternative is to just pass the responsibility down to the app developer to fill in a default: [someInput]="(value$ | async) || defaultValue"

@lacolaco
Copy link
Contributor

lacolaco commented Nov 9, 2019

Thank you for clarifying the problem. As a user, even if not Ivy, this has been a long-standing issue and very tough.

I think it isn't the child component's responsibility to be prepared for the possibility of null.
I am afraid that the design will be implicitly coupled with the parent implementation.
The parent component should be responsible for the value flowing through its own data stream, and that the non-nullable stream passes the value without null.

The trouble is that even if it is non-nullable, the value is not always available. It can delay.
Personally, I think that lazy execution approaches like React.lazy and React.Suspense may be helpful. <ng-container *ngIf="value$ | async as value"> is close to that but it rejects all falsy value. sometimes it occurs a bug with 0 or ''.

@Airblader
Copy link
Contributor

Airblader commented Nov 9, 2019

It would probably need to be done in a phased manner, while introducing something like asyncEager that maintains the old behavior to make migration easier.

Wouldn't it have to be the other way around, introduce the new behavior as asyncLazy, to not make a breaking change? Unless you intend to write a migration that changes all occurrences, but you'd also have to replace programmatic usages of the pipe.

Alternatively don't create a whole separate pipe but just make it accept a parameter for the initial value:

*ngIf="(foo$ | async: false) as foo" 

For simple type inputs a migration could be written that adds the respective default value of that type (boolean => false etc.) as the initial value. This is at least very likely to do the correct thing; if it wouldn't, the component would have a broken API because it should actually declare to expect null.

@mmalerba
Copy link
Contributor Author

@Airblader yeah I was thinking create a schematic to rename it, since we'd want to keep the async symbol for the non-deprecated version. Adding a fallback parameter to async pipe also seems like a good alternative, but I still think the best solution is not setting the input at all until the observable actually emits something

@kara kara added area: common Issues related to APIs in the @angular/common package comp: ivy labels Nov 11, 2019
@ngbot ngbot bot modified the milestone: needsTriage Nov 11, 2019
@IgorMinar
Copy link
Contributor

IgorMinar commented Nov 11, 2019

we discussed this today, and we agreed that to fix this properly, we should look at typing of inputs in general and properly allow inputs to be optional, required, etc.

for v9 the best we can likely do is that for users that want to use strictTemplates and strictNullChecks together, they can opt out of strict null typecheck specifically for input bindings via strictNullInputTypes : https://v9.angular.io/guide/template-typecheck#troubleshooting-template-errors

This should be explicitly documented in the v9 updating guide or template type checking guide.

@manughub
Copy link
Contributor

The docs changes have landed. Is there anything else required for this or can we close the issue @alxhub

@manughub manughub modified the milestones: v9-blockers, v10-candidates Dec 16, 2019
@alxhub
Copy link
Member

alxhub commented Jan 23, 2020

I consider this resolved. With the way Angular works today, at runtime the async pipe will set a null value into inputs. I think that strictTemplates should be enforcing that this is possible, unless you explicitly opt out (strictNullInputTypes: false).

@alxhub alxhub closed this as completed Jan 23, 2020
@Splaktar
Copy link
Member

we agreed that to fix this properly, we should look at typing of inputs in general and properly allow inputs to be optional, required, etc.

@IgorMinar is this tracked in an existing issue on GitHub or Jira?

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Feb 26, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: common Issues related to APIs in the @angular/common package
Projects
None yet
Development

No branches or pull requests

8 participants