Skip to content

Type guards ignored in closure #38755

Description

@hgl

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:

Activity

  1. hgl commented on May 24, 2020

    @hgl
    Author

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

  2. MartinJohns commented on May 24, 2020

    @MartinJohns
    Contributor

    Duplicate of #9998.

  3. hgl commented on May 24, 2020

    @hgl
    Author

    Thanks

  4. hgl commented on May 24, 2020

    @hgl
    Author

    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.

  5. ahejlsberg commented on May 25, 2020

    @ahejlsberg
    Member

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions