microsoft/TypeScript

Tuple destructuring type is different for different `target` options.

nicu-chiciuc opened this issue · 1 comments

TypeScript Version: 3.9.0-dev.20200226

Search Terms: target, indexing, tuple, destructuring, array, undefined, es5

Code

const arr: Array<string> = [];

const [first] = arr;
const zero = arr[0];

const str1: string = first;
const str2: string = zero;

also patch lib.es5.d.ts
from

 interface Array<T> {
  //...
  [n: number]: T;
 }

to

 interface Array<T> {
  //...
  [n: number]: T | undefined;
 }

Expected behavior:
Expect tsc to report 2 errors irrelevant of which target version is selected.

Actual behavior:
When using option "target": "es6":

src/index.ts:8:9 - error TS2322: Type 'string | undefined' is not assignable to type 'string'.
  Type 'undefined' is not assignable to type 'string'.

8   const str2: string = zero;
          ~~~~


Found 1 error.

When using option "target": "es5":

src/index.ts:6:7 - error TS2322: Type 'string | undefined' is not assignable to type 'string'.
  Type 'undefined' is not assignable to type 'string'.

6 const str1: string = first;
        ~~~~

src/index.ts:7:7 - error TS2322: Type 'string | undefined' is not assignable to type 'string'.
  Type 'undefined' is not assignable to type 'string'.

7 const str2: string = zero;
        ~~~~


Found 2 errors.

Playground Link: https://github.com/nicu-chiciuc/typescript-issue-001

Related Issues:
#13778
#36635

The whole idea of chaining the indexing definition for arrays comes from the first issue and mentioned this problem in this comment.
I didn't realize that the behavior depends on the version of the target option.

Some level of difference should be expected here since since we know that when targeting ES5 this will be downleveled to arr[0], whereas in a native ES6 runtime this will go through the Iterable protocol and possibly produce different results.

It looks like we have some shortcut paths in the checker that assume an Iterable from Array<T> will produce T when determining the iteration path. We could probably change that to be slower if multiple people need this support.