Skip to content

Commit c3d7a56

Browse files
Josh Goldbergsandersn
Josh Goldberg
andauthored
Specified diagnostic for iterating known array type without --downlevelIteration (microsoft#40070)
* Specified error message for iterating known array types without --downlevelIteration * Added extra target info to diagnostic * NodeList too, a classic * PR feedback: invert to allowsStrings; required param Co-authored-by: Nathan Shively-Sanders <[email protected]>
1 parent 7fca926 commit c3d7a56

11 files changed

+653
-12
lines changed

src/compiler/checker.ts

+41-12
Original file line numberDiff line numberDiff line change
@@ -34905,18 +34905,8 @@ namespace ts {
3490534905
// want to say that number is not an array type. But if the input was just
3490634906
// number and string input is allowed, we want to say that number is not an
3490734907
// array type or a string type.
34908-
const yieldType = getIterationTypeOfIterable(use, IterationTypeKind.Yield, inputType, /*errorNode*/ undefined);
34909-
const [defaultDiagnostic, maybeMissingAwait]: [DiagnosticMessage, boolean] = !(use & IterationUse.AllowsStringInputFlag) || hasStringConstituent
34910-
? downlevelIteration
34911-
? [Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true]
34912-
: yieldType
34913-
? [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_Use_compiler_option_downlevelIteration_to_allow_iterating_of_iterators, false]
34914-
: [Diagnostics.Type_0_is_not_an_array_type, true]
34915-
: downlevelIteration
34916-
? [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true]
34917-
: yieldType
34918-
? [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_Use_compiler_option_downlevelIteration_to_allow_iterating_of_iterators, false]
34919-
: [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type, true];
34908+
const allowsStrings = !!(use & IterationUse.AllowsStringInputFlag) && !hasStringConstituent;
34909+
const [defaultDiagnostic, maybeMissingAwait] = getIterationDiagnosticDetails(allowsStrings, downlevelIteration);
3492034910
errorAndMaybeSuggestAwait(
3492134911
errorNode,
3492234912
maybeMissingAwait && !!getAwaitedTypeOfPromise(arrayType),
@@ -34937,6 +34927,45 @@ namespace ts {
3493734927
}
3493834928

3493934929
return (use & IterationUse.PossiblyOutOfBounds) ? includeUndefinedInIndexSignature(arrayElementType) : arrayElementType;
34930+
34931+
function getIterationDiagnosticDetails(allowsStrings: boolean, downlevelIteration: boolean | undefined): [DiagnosticMessage, boolean] {
34932+
if (downlevelIteration) {
34933+
return allowsStrings
34934+
? [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true]
34935+
: [Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true];
34936+
}
34937+
34938+
const yieldType = getIterationTypeOfIterable(use, IterationTypeKind.Yield, inputType, /*errorNode*/ undefined);
34939+
34940+
if (yieldType) {
34941+
return [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_Use_compiler_option_downlevelIteration_to_allow_iterating_of_iterators, false];
34942+
}
34943+
34944+
if (isES2015OrLaterIterable(inputType.symbol?.escapedName)) {
34945+
return [Diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, true];
34946+
}
34947+
34948+
return allowsStrings
34949+
? [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type, true]
34950+
: [Diagnostics.Type_0_is_not_an_array_type, true];
34951+
}
34952+
}
34953+
34954+
function isES2015OrLaterIterable(n: __String) {
34955+
switch (n) {
34956+
case "Float32Array":
34957+
case "Float64Array":
34958+
case "Int16Array":
34959+
case "Int32Array":
34960+
case "Int8Array":
34961+
case "NodeList":
34962+
case "Uint16Array":
34963+
case "Uint32Array":
34964+
case "Uint8Array":
34965+
case "Uint8ClampedArray":
34966+
return true;
34967+
}
34968+
return false;
3494034969
}
3494134970

3494234971
/**

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -3260,6 +3260,10 @@
32603260
"category": "Error",
32613261
"code": 2801
32623262
},
3263+
"Type '{0}' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.": {
3264+
"category": "Error",
3265+
"code": 2802
3266+
},
32633267

32643268
"Import declaration '{0}' is using private name '{1}'.": {
32653269
"category": "Error",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
tests/cases/compiler/typedArrays-es5.ts(2,5): error TS2802: Type 'Float32Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
2+
tests/cases/compiler/typedArrays-es5.ts(5,5): error TS2802: Type 'Float64Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
3+
tests/cases/compiler/typedArrays-es5.ts(8,5): error TS2802: Type 'Int16Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
4+
tests/cases/compiler/typedArrays-es5.ts(11,5): error TS2802: Type 'Int32Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
5+
tests/cases/compiler/typedArrays-es5.ts(14,5): error TS2802: Type 'Int8Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
6+
tests/cases/compiler/typedArrays-es5.ts(17,5): error TS2802: Type 'NodeList' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
7+
tests/cases/compiler/typedArrays-es5.ts(20,5): error TS2802: Type 'Uint16Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
8+
tests/cases/compiler/typedArrays-es5.ts(23,5): error TS2802: Type 'Uint32Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
9+
tests/cases/compiler/typedArrays-es5.ts(26,5): error TS2802: Type 'Uint8Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
10+
tests/cases/compiler/typedArrays-es5.ts(29,5): error TS2802: Type 'Uint8ClampedArray' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
11+
12+
13+
==== tests/cases/compiler/typedArrays-es5.ts (10 errors) ====
14+
const float32Array = new Float32Array(1);
15+
[...float32Array];
16+
~~~~~~~~~~~~
17+
!!! error TS2802: Type 'Float32Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
18+
19+
const float64Array = new Float64Array(1);
20+
[...float64Array];
21+
~~~~~~~~~~~~
22+
!!! error TS2802: Type 'Float64Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
23+
24+
const int16Array = new Int16Array(1);
25+
[...int16Array];
26+
~~~~~~~~~~
27+
!!! error TS2802: Type 'Int16Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
28+
29+
const int32Array = new Int32Array(1);
30+
[...int32Array];
31+
~~~~~~~~~~
32+
!!! error TS2802: Type 'Int32Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
33+
34+
const int8Array = new Int8Array(1);
35+
[...int8Array];
36+
~~~~~~~~~
37+
!!! error TS2802: Type 'Int8Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
38+
39+
const nodeList = new NodeList();
40+
[...nodeList];
41+
~~~~~~~~
42+
!!! error TS2802: Type 'NodeList' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
43+
44+
const uint16Array = new Uint16Array(1);
45+
[...uint16Array];
46+
~~~~~~~~~~~
47+
!!! error TS2802: Type 'Uint16Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
48+
49+
const uint32Array = new Uint32Array(1);
50+
[...uint32Array];
51+
~~~~~~~~~~~
52+
!!! error TS2802: Type 'Uint32Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
53+
54+
const uint8Array = new Uint8Array(1);
55+
[...uint8Array];
56+
~~~~~~~~~~
57+
!!! error TS2802: Type 'Uint8Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
58+
59+
const uint8ClampedArray = new Uint8ClampedArray(1);
60+
[...uint8ClampedArray];
61+
~~~~~~~~~~~~~~~~~
62+
!!! error TS2802: Type 'Uint8ClampedArray' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
63+
64+
65+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//// [typedArrays-es5.ts]
2+
const float32Array = new Float32Array(1);
3+
[...float32Array];
4+
5+
const float64Array = new Float64Array(1);
6+
[...float64Array];
7+
8+
const int16Array = new Int16Array(1);
9+
[...int16Array];
10+
11+
const int32Array = new Int32Array(1);
12+
[...int32Array];
13+
14+
const int8Array = new Int8Array(1);
15+
[...int8Array];
16+
17+
const nodeList = new NodeList();
18+
[...nodeList];
19+
20+
const uint16Array = new Uint16Array(1);
21+
[...uint16Array];
22+
23+
const uint32Array = new Uint32Array(1);
24+
[...uint32Array];
25+
26+
const uint8Array = new Uint8Array(1);
27+
[...uint8Array];
28+
29+
const uint8ClampedArray = new Uint8ClampedArray(1);
30+
[...uint8ClampedArray];
31+
32+
33+
34+
35+
//// [typedArrays-es5.js]
36+
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
37+
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
38+
to[j] = from[i];
39+
return to;
40+
};
41+
var float32Array = new Float32Array(1);
42+
__spreadArray([], float32Array);
43+
var float64Array = new Float64Array(1);
44+
__spreadArray([], float64Array);
45+
var int16Array = new Int16Array(1);
46+
__spreadArray([], int16Array);
47+
var int32Array = new Int32Array(1);
48+
__spreadArray([], int32Array);
49+
var int8Array = new Int8Array(1);
50+
__spreadArray([], int8Array);
51+
var nodeList = new NodeList();
52+
__spreadArray([], nodeList);
53+
var uint16Array = new Uint16Array(1);
54+
__spreadArray([], uint16Array);
55+
var uint32Array = new Uint32Array(1);
56+
__spreadArray([], uint32Array);
57+
var uint8Array = new Uint8Array(1);
58+
__spreadArray([], uint8Array);
59+
var uint8ClampedArray = new Uint8ClampedArray(1);
60+
__spreadArray([], uint8ClampedArray);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
=== tests/cases/compiler/typedArrays-es5.ts ===
2+
const float32Array = new Float32Array(1);
3+
>float32Array : Symbol(float32Array, Decl(typedArrays-es5.ts, 0, 5))
4+
>Float32Array : Symbol(Float32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
5+
6+
[...float32Array];
7+
>float32Array : Symbol(float32Array, Decl(typedArrays-es5.ts, 0, 5))
8+
9+
const float64Array = new Float64Array(1);
10+
>float64Array : Symbol(float64Array, Decl(typedArrays-es5.ts, 3, 5))
11+
>Float64Array : Symbol(Float64Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
12+
13+
[...float64Array];
14+
>float64Array : Symbol(float64Array, Decl(typedArrays-es5.ts, 3, 5))
15+
16+
const int16Array = new Int16Array(1);
17+
>int16Array : Symbol(int16Array, Decl(typedArrays-es5.ts, 6, 5))
18+
>Int16Array : Symbol(Int16Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
19+
20+
[...int16Array];
21+
>int16Array : Symbol(int16Array, Decl(typedArrays-es5.ts, 6, 5))
22+
23+
const int32Array = new Int32Array(1);
24+
>int32Array : Symbol(int32Array, Decl(typedArrays-es5.ts, 9, 5))
25+
>Int32Array : Symbol(Int32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
26+
27+
[...int32Array];
28+
>int32Array : Symbol(int32Array, Decl(typedArrays-es5.ts, 9, 5))
29+
30+
const int8Array = new Int8Array(1);
31+
>int8Array : Symbol(int8Array, Decl(typedArrays-es5.ts, 12, 5))
32+
>Int8Array : Symbol(Int8Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
33+
34+
[...int8Array];
35+
>int8Array : Symbol(int8Array, Decl(typedArrays-es5.ts, 12, 5))
36+
37+
const nodeList = new NodeList();
38+
>nodeList : Symbol(nodeList, Decl(typedArrays-es5.ts, 15, 5))
39+
>NodeList : Symbol(NodeList, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
40+
41+
[...nodeList];
42+
>nodeList : Symbol(nodeList, Decl(typedArrays-es5.ts, 15, 5))
43+
44+
const uint16Array = new Uint16Array(1);
45+
>uint16Array : Symbol(uint16Array, Decl(typedArrays-es5.ts, 18, 5))
46+
>Uint16Array : Symbol(Uint16Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
47+
48+
[...uint16Array];
49+
>uint16Array : Symbol(uint16Array, Decl(typedArrays-es5.ts, 18, 5))
50+
51+
const uint32Array = new Uint32Array(1);
52+
>uint32Array : Symbol(uint32Array, Decl(typedArrays-es5.ts, 21, 5))
53+
>Uint32Array : Symbol(Uint32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
54+
55+
[...uint32Array];
56+
>uint32Array : Symbol(uint32Array, Decl(typedArrays-es5.ts, 21, 5))
57+
58+
const uint8Array = new Uint8Array(1);
59+
>uint8Array : Symbol(uint8Array, Decl(typedArrays-es5.ts, 24, 5))
60+
>Uint8Array : Symbol(Uint8Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
61+
62+
[...uint8Array];
63+
>uint8Array : Symbol(uint8Array, Decl(typedArrays-es5.ts, 24, 5))
64+
65+
const uint8ClampedArray = new Uint8ClampedArray(1);
66+
>uint8ClampedArray : Symbol(uint8ClampedArray, Decl(typedArrays-es5.ts, 27, 5))
67+
>Uint8ClampedArray : Symbol(Uint8ClampedArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
68+
69+
[...uint8ClampedArray];
70+
>uint8ClampedArray : Symbol(uint8ClampedArray, Decl(typedArrays-es5.ts, 27, 5))
71+
72+
73+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
=== tests/cases/compiler/typedArrays-es5.ts ===
2+
const float32Array = new Float32Array(1);
3+
>float32Array : Float32Array
4+
>new Float32Array(1) : Float32Array
5+
>Float32Array : Float32ArrayConstructor
6+
>1 : 1
7+
8+
[...float32Array];
9+
>[...float32Array] : any[]
10+
>...float32Array : any
11+
>float32Array : Float32Array
12+
13+
const float64Array = new Float64Array(1);
14+
>float64Array : Float64Array
15+
>new Float64Array(1) : Float64Array
16+
>Float64Array : Float64ArrayConstructor
17+
>1 : 1
18+
19+
[...float64Array];
20+
>[...float64Array] : any[]
21+
>...float64Array : any
22+
>float64Array : Float64Array
23+
24+
const int16Array = new Int16Array(1);
25+
>int16Array : Int16Array
26+
>new Int16Array(1) : Int16Array
27+
>Int16Array : Int16ArrayConstructor
28+
>1 : 1
29+
30+
[...int16Array];
31+
>[...int16Array] : any[]
32+
>...int16Array : any
33+
>int16Array : Int16Array
34+
35+
const int32Array = new Int32Array(1);
36+
>int32Array : Int32Array
37+
>new Int32Array(1) : Int32Array
38+
>Int32Array : Int32ArrayConstructor
39+
>1 : 1
40+
41+
[...int32Array];
42+
>[...int32Array] : any[]
43+
>...int32Array : any
44+
>int32Array : Int32Array
45+
46+
const int8Array = new Int8Array(1);
47+
>int8Array : Int8Array
48+
>new Int8Array(1) : Int8Array
49+
>Int8Array : Int8ArrayConstructor
50+
>1 : 1
51+
52+
[...int8Array];
53+
>[...int8Array] : any[]
54+
>...int8Array : any
55+
>int8Array : Int8Array
56+
57+
const nodeList = new NodeList();
58+
>nodeList : NodeList
59+
>new NodeList() : NodeList
60+
>NodeList : { new (): NodeList; prototype: NodeList; }
61+
62+
[...nodeList];
63+
>[...nodeList] : any[]
64+
>...nodeList : any
65+
>nodeList : NodeList
66+
67+
const uint16Array = new Uint16Array(1);
68+
>uint16Array : Uint16Array
69+
>new Uint16Array(1) : Uint16Array
70+
>Uint16Array : Uint16ArrayConstructor
71+
>1 : 1
72+
73+
[...uint16Array];
74+
>[...uint16Array] : any[]
75+
>...uint16Array : any
76+
>uint16Array : Uint16Array
77+
78+
const uint32Array = new Uint32Array(1);
79+
>uint32Array : Uint32Array
80+
>new Uint32Array(1) : Uint32Array
81+
>Uint32Array : Uint32ArrayConstructor
82+
>1 : 1
83+
84+
[...uint32Array];
85+
>[...uint32Array] : any[]
86+
>...uint32Array : any
87+
>uint32Array : Uint32Array
88+
89+
const uint8Array = new Uint8Array(1);
90+
>uint8Array : Uint8Array
91+
>new Uint8Array(1) : Uint8Array
92+
>Uint8Array : Uint8ArrayConstructor
93+
>1 : 1
94+
95+
[...uint8Array];
96+
>[...uint8Array] : any[]
97+
>...uint8Array : any
98+
>uint8Array : Uint8Array
99+
100+
const uint8ClampedArray = new Uint8ClampedArray(1);
101+
>uint8ClampedArray : Uint8ClampedArray
102+
>new Uint8ClampedArray(1) : Uint8ClampedArray
103+
>Uint8ClampedArray : Uint8ClampedArrayConstructor
104+
>1 : 1
105+
106+
[...uint8ClampedArray];
107+
>[...uint8ClampedArray] : any[]
108+
>...uint8ClampedArray : any
109+
>uint8ClampedArray : Uint8ClampedArray
110+
111+
112+

0 commit comments

Comments
 (0)