Skip to content

Type of object property isn’t narrowed when captured by closure #51490

Closed
@leafac

Description

@leafac

Bug Report

🔎 Search Terms

“TypeScript narrowing of object field captured in closure”

I found #35124 and #9998 but they aren’t quite the same thing.

In my case, it’s an issue that only occurs with object properties, not bare variables like in #35124.

Also, my version is relying on return to avoid creating the closure that would have captured the variable in the first place.

🕗 Version & Regression Information

  • This is a crash
  • This changed between versions ______ and _______
  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about “narrowing”
  • I was unable to test this on prior versions because _______

⏯ Playground Link

Playground link with relevant code

💻 Code

(argument: { field: "a" | "b" }) => {
    if (argument.field === "a") return;
    argument.field; // The type of ‘argument.field’ is just ‘"b"’ at this point, because of ‘return’ above.
    () => {
        argument.field; // The type of ‘argument.field’ is back to being ‘"a" | "b"’. I suppose this shouldn’t happen...
    }
};

(argument: "a" | "b") => {
    if (argument === "a") return;
    argument; // Same as above, the type of ‘argument’ is just ‘"b"’ at this point, because of ‘return’ above.
    () => {
        argument; // And here the type of ‘argument’ continues to be ‘"b"’, as I think it should.
    }
};

🙁 Actual behavior

Type of object property isn’t narrowed when captured by closure, like a bare variable is.

The only workaround I could find is the check for the condition again in the closure:

(argument: { field: "a" | "b" }) => {
    if (argument.field === "a") return;
    argument.field; // The type of ‘argument.field’ is just ‘"b"’ at this point, because of ‘return’ above.
    () => {
        if (argument.field === "a") return; // Naturally, this repeated check makes narrowing work.
        argument.field;
    }
};

🙂 Expected behavior

Type of object property should be narrowed when captured by closure, like a bare variable is.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions