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

Type guards ignored in closure #38755

Closed
hgl opened this issue May 24, 2020 · 5 comments · Fixed by #56908
Closed

Type guards ignored in closure #38755

hgl opened this issue May 24, 2020 · 5 comments · Fixed by #56908
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@hgl
Copy link

hgl commented May 24, 2020

TypeScript Version:
v4.0.0-dev.20200523

Search Terms:
type guard closure
Code

let data: {[k: string]: string} = {}
function deleteOnClick() {
    let key = findKey()
    if (!key) {
        return;
    }
    let key2 = key
    window.addEventListener("click", () => {
        delete data[key2] // this is ok
        delete data[key] // type error, key can be null
    })
}

function findKey(): string | null {
    return null
}

Expected behavior:
delete data[key] contains no error
Actual behavior:
delete data[key] contains type error

Playground Link:
https://www.typescriptlang.org/play/?#code/DYUwLgBAJghmMC4IG8DaBrJBnMAnAlgHYDmAutnkcQL4QC8K1AUAGYCuhAxmPgPaHQQoMCADyhAMLB8ndAAoAlCiYRVEYRHQgAnvQgsiUANI7FKtfhYQ5AQi3alyc2rW5wbXIQDcziMxca9gBMeva+AO6GvOEAdDBQUACiAG4ghGAAMvg4aSC4cgBEnNKyBQA01kp0AHzKLi5QQuAg0HAwGDpBpBAA9D0QYAAW2RAjvOi+DU0irfAd2t19A9oADi15uLy4FfYQnDACAEYthGzAwL7UCkzMrBzcfAIGhMamChQEJBAAPhCn53VXO5PH8zhdqEA
Related Issues:

@hgl
Copy link
Author

hgl commented May 24, 2020

Asked on SO, doesn't get any response. Looks like a bug to me.

@MartinJohns
Copy link
Contributor

Duplicate of #9998.

@hgl
Copy link
Author

hgl commented May 24, 2020

Thanks

@hgl hgl closed this as completed May 24, 2020
@hgl
Copy link
Author

hgl commented May 24, 2020

On second thought this doesn’t seem to be a duplicate. key is locally defined, there is no way the addEventListener call can reset it back to null.

Not sure it’s flow control related.

@hgl hgl reopened this May 24, 2020
@ahejlsberg
Copy link
Member

ahejlsberg commented May 25, 2020

This is a design limitation. When a local variable is declared with let or var the control flow analyzer assumes that there could be subsequent assignments to the variable following the creation of a closure that references the variable, and therefore that narrowed types may no longer be correct (it's just that there aren't any such assignments in your example). Your example works if you use const in the declaration of key because it is then known that there won't be any further assignments and that it is safe to carry the narrowed types into the closure.

We could theoretically do more work in the control flow analyzer to determine that there are no assignments to a particular variable following the creation of a function closure that references the variable, but it's not trivial.

@ahejlsberg ahejlsberg added the Design Limitation Constraints of the existing architecture prevent this from being fixed label May 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants