Skip to content

Support preserving type narrowing inside closures in some simple casesΒ #55528

Closed
@fabiospampinato

Description

@fabiospampinato

πŸ” Search Terms

  • narrowing
  • type
  • closure
  • function

βœ… Viability Checklist

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals

⭐ Suggestion

I understand that types are not kept narrowed inside callbacks because the narrowing could in general not hold anymore in there, however there are some "simple" scenarios where we can be sure that the narrowing holds, for example:

function foo () {

  let maybe: string | null;

  maybe = 'foo';

  console.log ( () => {

    maybe;
    // ^?

  });  

}

This scenario is a sort of a simple edge case of the general problem because:

  • The maybe variable holds a primitive value, so it will be passed to other functions by copy, so those functions outside the closure can't change its value inside the closure.
  • The code executed before the console.log call is done forever, since it doesn't have any callbacks that assign to maybe, and it's not wrapped in an unterminated loop.
  • The "code" after the console.log call also has no assignments to "maybe", in fact it has no references to "maybe" at all.

Under these conditions it's impossible for narrowing the type inside our function in the example above to be wrong, so it should be preserved.

πŸ“ƒ Motivating Example

Playground: https://www.typescriptlang.org/play?#code/FAMwrgdgxgLglgewgAhAhyAUBKZBvYYZZAGwFMZkBbAQwE8AjMgLmQGcYAnOCAc2QA+yCGBIkA3IWK1GZZAF5kAcjQIlkosihI2CcgDoSCfpiy55APnxTi1ek0m3kAemfIAegH4bAX2zjiQh9gIA

πŸ’» Use Cases

Preserving narrowing in simple cases like the one mentioned above is very handy and allows the user to write clean code in more scenarios.

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