TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Improve binding element type inference

Open babakks opened this issue 3 years ago • 0 comments

Fixes #49989

Problem

There were two problems:

  1. Type inference for variables declared by binding elements was not accurate. For example, for the declaration below the type of both variables were inferred to be any (instead of number).

    const [a, b = a] = [1];
    
  2. With noImplicitAny option enabled, a false circular relationship error would be emitted:

    'a' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)
    

Cause

The problems were hidden in the getTypeFromBindingElement function whose responsibility is to infer the type of variables defined as binding elements without looking onto the declaration initializer (the array literal, [1], in the example above).

When a binding element itself had a default value (as in b = a) and that default value involved any sibling variable (i.e., variables defined in the same binding pattern, here a) then the inquiry for the type of the default value would begin and eventually result in a circular relationship error down the path. This error made the type checker to infer the types as any.

Solution

Since the getTypeFromBindingElement function just needs to narrowly look inside the binding elements/patterns, we can skip further type checkings (that is falling back to any) when any other sibling variables are somehow involved in the default value expressions.

Although this seems to be an ad-hoc/one-off kind of solution, type checkings for binding elements are deeply integrated with other parts of the type checker, and solving the problem in a more generic way, I believe, requires greater knowledge of the code base (compared to mine, of course).

Effect on the existing behavior

Three existing test cases were affected by this PR, fortunately in a good way. They're now correctly inferring the type number. Also, the circular relationship error was erased from one similar test case.

New test case

A new test case, destructuringArrayBindingPatternAndAssignment5.ts, was added that contains cases where default values somehow reference other sibling variables.

babakks avatar Aug 09 '22 20:08 babakks