Skip to content

Type narrowed too muchΒ #57880

@fjolliton

Description

@fjolliton

πŸ”Ž Search Terms

type narrowing local variable

πŸ•— Version & Regression Information

I don't see anything related in the FAQ. But I acknowledge that this seem too common to be unknown. Every version seem affected however.

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.4.2#code/MYewdgzgLgBMCGAbRMC8MAUAzAXJglGgHwwBuIAlgCaGolYb4DcAUC6JLFAKbRoHEYAbxYwxMRN1jw8AVzBVuWCmG5UYAHxhhZAWwBG3AE795i5aqqtxMAPS2YAFQCeAB17AjFV7AjduuhAwUCAwhnAguq6SPIjOMPLwAO7wRtzBABbwXBnppEiy3KLi9jAgWDAABvCVcPBgcFlgAObpKpnpWCDIIEkqzXXIAHTFYgjIGIyCQjDw-ACMTDAAvsyjdg4AggodaQA0MBS+UBTImSoA1pnZVTV1DeBx66WuIBAQFPpxYemVZkoqNSVEY2CgVDBzACEqHQ-wsakIIhsNlKUAyFCCiEBMFasDSACtuMAeFR1jZ4EMQgBlKBeFqMaziZYsZasIA

πŸ’» Code

const call = (f: () => void) => f();

const test = () => {
    let a: undefined | number = undefined;
    // Typescript seems to be completely unaware that the value
    // of `a` can change in the following call.
    call(() => { a = 1; });
    // And there, it still think that `a` can only
    // possibly be `undefined`.
    if (a !== undefined) {
        // this line get rejected
        a.toString();
    }
};

πŸ™ Actual behavior

It seems that Typescript is not considering a function call to affect local variable. It proceed to narrow the type from this limitation, and thus reject valid code.

Not assigning undefined to a causes the error to disappear BUT this is still a problem, because I might want a default value here (could be a number initially, that later get changed to undefined for example).

For example, and this is worse:

const call = (f: () => void) => f();

const test = () => {
    let a: undefined | number = 42;
    call(() => {
        a = undefined;
    });
    a.toString();
};

This will compile fine, but it will fail at runtime!

πŸ™‚ Expected behavior

The type should not be narrowed in this case.

Typescript should detect that a closure is referencing a local variable, and thus, should avoid narrowing its type.

Additional information about the issue

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions