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

Fix emit for optional chain with non-null assertion #36539

Merged
merged 4 commits into from Mar 25, 2020
Merged

Fix emit for optional chain with non-null assertion #36539

merged 4 commits into from Mar 25, 2020

Conversation

Copy link
Member

@rbuckton rbuckton commented Jan 31, 2020

Fixes emit for optional chaining when a non-null assertion is present in the chain:

// ts
obj?.a!.b

// js (old)
(obj === null || obj === void 0 ? void 0 : obj.a).b

// js (new)
obj === null || obj === void 0 ? void 0 : obj.a.b

Fixes #36031

@DanielRosenwasser
Copy link
Member

@DanielRosenwasser DanielRosenwasser commented Jan 31, 2020

Why did we decide not to change the types here? Seems like we really shouldn't have one without the other.

@rbuckton
Copy link
Member Author

@rbuckton rbuckton commented Feb 1, 2020

There are some odd quirks to consider if we change the precedence of !:

// note: `undefined*` indicates an `undefined` that was added to the type by `?.`
declare const a: undefined | { b: number | null };

// current behavior 
a!.b // number | null
a!.b! // number
a?.b // number | null | undefined*
a?.b! // number

// proposed behavior (differences) 
a?.b! // number | undefined*

If we give ! a lower precedence than ?. and OptionalChain, then it must always have a lower precedence than OptionalChain. With the proposed changes, to get the current behavior for a?.b! you would instead need to write (a?.b)!.

@sandersn sandersn added the For Milestone Bug label Feb 5, 2020
@sandersn sandersn added this to Not started in PR Backlog Feb 12, 2020
@rbuckton
Copy link
Member Author

@rbuckton rbuckton commented Feb 28, 2020

With the latest changes, a postfix-! inside of an optional chain will remove optionality only in the non-optional control flow branch, while a postfix-! at the end of an optional chain will remove optionality for the whole expression:

declare const a: undefined | { b: { c: number } | null };

a?.b.c; // error
a?.b!.c; // number | undefined
a?.b!; // { c: number }

This best matches user expectations.

@rbuckton rbuckton requested a review from elibarzilay Feb 28, 2020
# Conflicts:
#	src/compiler/debug.ts
PR Backlog automation moved this from Not started to Needs merge Feb 28, 2020
@DanielRosenwasser
Copy link
Member

@DanielRosenwasser DanielRosenwasser commented Feb 28, 2020

@typescript-bot pack this

@typescript-bot
Copy link
Collaborator

@typescript-bot typescript-bot commented Feb 28, 2020

Heya @DanielRosenwasser, I've started to run the tarball bundle task on this PR at 4214548. You can monitor the build here.

@DanielRosenwasser
Copy link
Member

@DanielRosenwasser DanielRosenwasser commented Feb 28, 2020

Do we have tests for

let x = a?.b!();

Copy link
Contributor

@elibarzilay elibarzilay left a comment

(To be taken with plenty of salt.)

src/compiler/binder.ts Outdated Show resolved Hide resolved
src/compiler/utilitiesPublic.ts Outdated Show resolved Hide resolved
@typescript-bot
Copy link
Collaborator

@typescript-bot typescript-bot commented Feb 28, 2020

Hey @DanielRosenwasser, I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
    "devDependencies": {
        "typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/66655/artifacts?artifactName=tgz&fileId=96C836092C4432923665DCDF014700A31A0F45018B869320D4A73487C34B8B9E02&fileName=/typescript-3.9.0-insiders.20200228.tgz"
    }
}

and then running npm install.


There is also a playground for this build.

@sandersn
Copy link
Member

@sandersn sandersn commented Mar 12, 2020

@rbuckton is this ready to merge?

@DanielRosenwasser
Copy link
Member

@DanielRosenwasser DanielRosenwasser commented Mar 25, 2020

@rbuckton @RyanCavanaugh this should have landed in the beta

@DanielRosenwasser
Copy link
Member

@DanielRosenwasser DanielRosenwasser commented Mar 25, 2020

@typescript-bot user test this
@typescript-bot test this

@typescript-bot
Copy link
Collaborator

@typescript-bot typescript-bot commented Mar 25, 2020

Heya @DanielRosenwasser, I've started to run the parallelized community code test suite on this PR at 4214548. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

@typescript-bot typescript-bot commented Mar 25, 2020

Heya @DanielRosenwasser, I've started to run the extended test suite on this PR at 4214548. You can monitor the build here.

@DanielRosenwasser
Copy link
Member

@DanielRosenwasser DanielRosenwasser commented Mar 25, 2020

@typescript-bot cherry-pick this to release-3.9

@typescript-bot
Copy link
Collaborator

@typescript-bot typescript-bot commented Mar 25, 2020

Heya @DanielRosenwasser, I've started to run the task to cherry-pick this into release-3.9 on this PR at 4214548. You can monitor the build here.

typescript-bot pushed a commit to typescript-bot/TypeScript that referenced this issue Mar 25, 2020
Component commits:
0f8c1f7 Fix emit for optional chain with non-null assertion

d187ca7 Treat '!' differently inside chain vs end of chain

4214548 Merge branch 'master' into fix36031
# Conflicts:
#	src/compiler/debug.ts
@typescript-bot
Copy link
Collaborator

@typescript-bot typescript-bot commented Mar 25, 2020

Hey @DanielRosenwasser, I've opened #37599 for you.

@typescript-bot
Copy link
Collaborator

@typescript-bot typescript-bot commented Mar 25, 2020

The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master.

DanielRosenwasser pushed a commit that referenced this issue Mar 25, 2020
Component commits:
0f8c1f7 Fix emit for optional chain with non-null assertion

d187ca7 Treat '!' differently inside chain vs end of chain

4214548 Merge branch 'master' into fix36031
# Conflicts:
#	src/compiler/debug.ts

Co-authored-by: Ron Buckton <rbuckton@microsoft.com>
@rbuckton rbuckton merged commit b58a29b into master Mar 25, 2020
4 of 7 checks passed
PR Backlog automation moved this from Needs merge to Done Mar 25, 2020
@rbuckton
Copy link
Member Author

@rbuckton rbuckton commented Mar 25, 2020

@DanielRosenwasser I manually cherry-picked the last commit over, which just addresses @elibarzilay's comments about a dead-code branch and fixes a comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team For Milestone Bug
Projects
PR Backlog
  
Done
Development

Successfully merging this pull request may close these issues.

7 participants