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
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.