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

Narrowing on await #44858

Closed
reverofevil opened this issue Jul 1, 2021 · 7 comments
Closed

Narrowing on await #44858

reverofevil opened this issue Jul 1, 2021 · 7 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@reverofevil
Copy link

Bug Report

πŸ”Ž Search Terms

narrowing await

πŸ•— Version & Regression Information

This is the behavior in every version I tried, and I reviewed the FAQ for entries about Type System Behavior

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

let x: null | string = 'hello';
(async () => {
    if (typeof x !== 'string') {
        return;
    }
    await new Promise((resolve) => {
        x = null;
        setTimeout(resolve, 0);
    });
    // Cannot read property 'toString' of null
    console.log(x.toString());
})();

πŸ™ Actual behavior

x is narrowed to string, but await should have either extended it back to null | string, or narrowed it in the parameter of Promise constructor. toString gets called on null. In this way arbitrary type punning is possible.

πŸ™‚ Expected behavior

Code shouldn't have compiled.

@whzx5byb
Copy link

whzx5byb commented Jul 1, 2021

Even synchronous code can still produce the error.

let x: null | string = 'hello';
(() => {
    if (typeof x !== 'string') {
        return;
    }

    function fn() {
        x = null;
    }
    fn();
    
    // Cannot read property 'toString' of null
    console.log(x.toString());
})();

Because TS can't analyse every function to check if they change anything, so it treats every function as having no side-effect.
Related: #9998

@reverofevil
Copy link
Author

reverofevil commented Jul 2, 2021

Actually TS can analyze every function, by pure annotation. It's discussed in linked thread, and it's what tools like webpack use to make tree shaking possible.

@whzx5byb
Copy link

whzx5byb commented Jul 2, 2021

Actually TS can analyze every function, by pure annotation. It's discussed in linked thread, and it's what tools like webpack use to make tree shaking possible.

It is still in discussion. I guess you might be interested in #7770.

@reverofevil
Copy link
Author

reverofevil commented Jul 2, 2021

@whzx5byb Thank you! I would have spent quite some time looking for these links.

@MartinJohns
Copy link
Contributor

@polkovnikov-ph Basically any assignment via closure is missed by the compiler, due to #9998. Doesn't matter if async or sync.

#11498 is also a relevant issue to follow, although there is no progress at all.

@sandersn sandersn added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jul 2, 2021
@reverofevil
Copy link
Author

What a nice joke! Thank you!

@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

5 participants