-
Notifications
You must be signed in to change notification settings - Fork 12.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce checkElementTypeOfArrayOrString for downlevel for..of type …
…checking
- Loading branch information
1 parent
5b46f5f
commit 61cd2a7
Showing
39 changed files
with
685 additions
and
954 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1869,7 +1869,11 @@ module ts { | |
return anyType; | ||
} | ||
if (declaration.parent.parent.kind === SyntaxKind.ForOfStatement) { | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
JsonFreeman
Author
Contributor
|
||
return getTypeForVariableDeclarationInForOfStatement(<ForOfStatement>declaration.parent.parent); | ||
// checkRightHandSideOfForOf will return undefined if the for-of expression type was | ||
// missing properties/signatures required to get its iteratedType (like | ||
// [Symbol.iterator] or next). This may be because we accessed properties from anyType, | ||
// or it may have led to an error inside getIteratedType. | ||
return checkRightHandSideOfForOf((<ForOfStatement>declaration.parent.parent).expression) || anyType; | ||
} | ||
if (isBindingPattern(declaration.parent)) { | ||
return getTypeForBindingElement(<BindingElement>declaration); | ||
|
@@ -8781,16 +8785,15 @@ module ts { | |
|
||
// Check the LHS and RHS | ||
// If the LHS is a declaration, just check it as a variable declaration, which will in turn check the RHS | ||
// via getTypeForVariableDeclarationInForOfStatement. | ||
// via checkRightHandSideOfForOf. | ||
// If the LHS is an expression, check the LHS, as a destructuring assignment or as a reference. | ||
// Then check that the RHS is assignable to it. | ||
if (node.initializer.kind === SyntaxKind.VariableDeclarationList) { | ||
checkForInOrForOfVariableDeclaration(node); | ||
} | ||
else { | ||
var varExpr = <Expression>node.initializer; | ||
var rightType = checkExpression(node.expression); | ||
var iteratedType = checkIteratedType(rightType, node.expression); | ||
var iteratedType = checkRightHandSideOfForOf(node.expression); | ||
|
||
// There may be a destructuring assignment on the left side | ||
if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) { | ||
|
@@ -8872,18 +8875,11 @@ module ts { | |
} | ||
} | ||
|
||
function getTypeForVariableDeclarationInForOfStatement(forOfStatement: ForOfStatement): Type { | ||
// Temporarily return 'any' below ES6 | ||
if (languageVersion < ScriptTarget.ES6) { | ||
return anyType; | ||
} | ||
|
||
// iteratedType will be undefined if the for-of expression type was missing properties/signatures | ||
// required to get its iteratedType (like [Symbol.iterator] or next). This may be | ||
// because we accessed properties from anyType, or it may have led to an error inside | ||
// getIteratedType. | ||
var expressionType = getTypeOfExpression(forOfStatement.expression); | ||
return checkIteratedType(expressionType, forOfStatement.expression) || anyType; | ||
function checkRightHandSideOfForOf(rhsExpression: Expression): Type { | ||
var expressionType = getTypeOfExpression(rhsExpression); | ||
return languageVersion >= ScriptTarget.ES6 | ||
? checkIteratedType(expressionType, rhsExpression) | ||
: checkElementTypeOfArrayOrString(expressionType, rhsExpression); | ||
} | ||
|
||
/** | ||
|
@@ -8982,6 +8978,45 @@ module ts { | |
} | ||
} | ||
|
||
function checkElementTypeOfArrayOrString(arrayOrStringType: Type, expressionForError: Expression): Type { | ||
Debug.assert(languageVersion < ScriptTarget.ES6); | ||
var isJustString = allConstituentTypesHaveKind(arrayOrStringType, TypeFlags.StringLike); | ||
|
||
// Check isJustString because removeTypesFromUnionType will only remove types if it doesn't result | ||
// in an emptyObjectType. In this case, we actually do want the emptyObjectType. | ||
var arrayType = isJustString ? emptyObjectType : removeTypesFromUnionType(arrayOrStringType, TypeFlags.StringLike, /*isTypeOfKind*/ true); | ||
var hasStringConstituent = arrayOrStringType !== emptyObjectType && arrayOrStringType !== arrayType; | ||
|
||
var reportedError = false; | ||
if (hasStringConstituent && languageVersion < ScriptTarget.ES5) { | ||
error(expressionForError, Diagnostics.Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher); | ||
reportedError = true; | ||
} | ||
|
||
if (isJustString) { | ||
return stringType; | ||
} | ||
|
||
if (!isArrayLikeType(arrayType)) { | ||
if (!reportedError) { | ||
error(expressionForError, Diagnostics.Type_0_is_not_an_array_type, typeToString(arrayType)); | ||
} | ||
return hasStringConstituent ? stringType : unknownType; | ||
} | ||
|
||
var arrayElementType = getIndexTypeOfType(arrayType, IndexKind.Number) || unknownType; | ||
if (hasStringConstituent) { | ||
// This is just an optimization for the case where arrayOrStringType is string | string[] | ||
if (arrayElementType.flags & TypeFlags.StringLike) { | ||
return stringType; | ||
} | ||
|
||
return getUnionType([arrayElementType, stringType]); | ||
} | ||
|
||
return arrayElementType; | ||
} | ||
|
||
function checkBreakOrContinueStatement(node: BreakOrContinueStatement) { | ||
// Grammar checking | ||
checkGrammarStatementInAmbientContext(node) || checkGrammarBreakOrContinueStatement(node); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
=== tests/cases/conformance/statements/for-ofStatements/ES5For-of10.ts === | ||
function foo() { | ||
>foo : () => { x: number; } | ||
|
||
return { x: 0 }; | ||
>{ x: 0 } : { x: number; } | ||
>x : number | ||
} | ||
for (foo().x of []) { | ||
>foo().x : number | ||
>foo() : { x: number; } | ||
>foo : () => { x: number; } | ||
>x : number | ||
>[] : undefined[] | ||
|
||
for (foo().x of []) | ||
>foo().x : number | ||
>foo() : { x: number; } | ||
>foo : () => { x: number; } | ||
>x : number | ||
>[] : undefined[] | ||
|
||
var p = foo().x; | ||
>p : number | ||
>foo().x : number | ||
>foo() : { x: number; } | ||
>foo : () => { x: number; } | ||
>x : number | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
=== tests/cases/conformance/statements/for-ofStatements/ES5For-of11.ts === | ||
var v; | ||
>v : any | ||
|
||
for (v of []) { } | ||
>v : any | ||
>[] : undefined[] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of12.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of12.ts(1,6): error TS2461: Type 'undefined' is not an array type. | ||
|
||
|
||
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of12.ts (1 errors) ==== | ||
for ([""] of []) { } | ||
~~~ | ||
!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
~~~~ | ||
!!! error TS2461: Type 'undefined' is not an array type. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
=== tests/cases/conformance/statements/for-ofStatements/ES5For-of13.ts === | ||
for (let v of ['a', 'b', 'c']) { | ||
>v : string | ||
>['a', 'b', 'c'] : string[] | ||
|
||
var x = v; | ||
>x : string | ||
>v : string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
=== tests/cases/conformance/statements/for-ofStatements/ES5For-of24.ts === | ||
var a = [1, 2, 3]; | ||
>a : number[] | ||
>[1, 2, 3] : number[] | ||
|
||
for (var v of a) { | ||
>v : number | ||
>a : number[] | ||
|
||
let a = 0; | ||
>a : number | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
=== tests/cases/conformance/statements/for-ofStatements/ES5For-of25.ts === | ||
var a = [1, 2, 3]; | ||
>a : number[] | ||
>[1, 2, 3] : number[] | ||
|
||
for (var v of a) { | ||
>v : number | ||
>a : number[] | ||
|
||
v; | ||
>v : number | ||
|
||
a; | ||
>a : number[] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of26.ts(1,10): error TS2461: Type 'number' is not an array type. | ||
|
||
|
||
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of26.ts (1 errors) ==== | ||
for (var [a = 0, b = 1] of [2, 3]) { | ||
~~~~~~~~~~~~~~ | ||
!!! error TS2461: Type 'number' is not an array type. | ||
a; | ||
b; | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,13 @@ | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of27.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of27.ts(1,11): error TS2459: Type 'number' has no property 'x' and no string index signature. | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of27.ts(1,21): error TS2459: Type 'number' has no property 'y' and no string index signature. | ||
|
||
|
||
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of27.ts (1 errors) ==== | ||
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of27.ts (2 errors) ==== | ||
for (var {x: a = 0, y: b = 1} of [2, 3]) { | ||
~~~ | ||
!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
~ | ||
!!! error TS2459: Type 'number' has no property 'x' and no string index signature. | ||
~ | ||
!!! error TS2459: Type 'number' has no property 'y' and no string index signature. | ||
a; | ||
b; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of28.ts(1,10): error TS2461: Type 'number' is not an array type. | ||
|
||
|
||
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of28.ts (1 errors) ==== | ||
for (let [a = 0, b = 1] of [2, 3]) { | ||
~~~~~~~~~~~~~~ | ||
!!! error TS2461: Type 'number' is not an array type. | ||
a; | ||
b; | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,13 @@ | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of29.ts(1,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of29.ts(1,13): error TS2459: Type 'number' has no property 'x' and no string index signature. | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of29.ts(1,23): error TS2459: Type 'number' has no property 'y' and no string index signature. | ||
|
||
|
||
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of29.ts (1 errors) ==== | ||
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of29.ts (2 errors) ==== | ||
for (const {x: a = 0, y: b = 1} of [2, 3]) { | ||
~~~ | ||
!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
~ | ||
!!! error TS2459: Type 'number' has no property 'x' and no string index signature. | ||
~ | ||
!!! error TS2459: Type 'number' has no property 'y' and no string index signature. | ||
a; | ||
b; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
=== tests/cases/conformance/statements/for-ofStatements/ES5For-of3.ts === | ||
for (var v of ['a', 'b', 'c']) | ||
>v : string | ||
>['a', 'b', 'c'] : string[] | ||
|
||
var x = v; | ||
>x : string | ||
>v : string | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,6): error TS2461: Type 'string | number' is not an array type. | ||
|
||
|
||
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts (1 errors) ==== | ||
var a: string, b: number; | ||
var tuple: [number, string] = [2, "3"]; | ||
for ([a = 1, b = ""] of tuple) { | ||
~~~ | ||
!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
~~~~~~~~~~~~~~~ | ||
!!! error TS2461: Type 'string | number' is not an array type. | ||
a; | ||
b; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,15 @@ | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of31.ts(3,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of31.ts(3,8): error TS2459: Type 'undefined' has no property 'a' and no string index signature. | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of31.ts(3,18): error TS2459: Type 'undefined' has no property 'b' and no string index signature. | ||
|
||
|
||
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of31.ts (1 errors) ==== | ||
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of31.ts (2 errors) ==== | ||
var a: string, b: number; | ||
|
||
for ({ a: b = 1, b: a = ""} of []) { | ||
~~~ | ||
!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
~ | ||
!!! error TS2459: Type 'undefined' has no property 'a' and no string index signature. | ||
~ | ||
!!! error TS2459: Type 'undefined' has no property 'b' and no string index signature. | ||
a; | ||
b; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of8.ts(4,1): error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
tests/cases/conformance/statements/for-ofStatements/ES5For-of8.ts(4,6): error TS2322: Type 'string' is not assignable to type 'number'. | ||
|
||
|
||
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of8.ts (1 errors) ==== | ||
function foo() { | ||
return { x: 0 }; | ||
} | ||
for (foo().x of ['a', 'b', 'c']) { | ||
~~~ | ||
!!! error TS2482: 'for...of' statements are only available when targeting ECMAScript 6 or higher. | ||
~~~~~~~ | ||
!!! error TS2322: Type 'string' is not assignable to type 'number'. | ||
var p = foo().x; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
=== tests/cases/conformance/statements/for-ofStatements/ES5For-of9.ts === | ||
function foo() { | ||
>foo : () => { x: number; } | ||
|
||
return { x: 0 }; | ||
>{ x: 0 } : { x: number; } | ||
>x : number | ||
} | ||
for (foo().x of []) { | ||
>foo().x : number | ||
>foo() : { x: number; } | ||
>foo : () => { x: number; } | ||
>x : number | ||
>[] : undefined[] | ||
|
||
for (foo().x of []) { | ||
>foo().x : number | ||
>foo() : { x: number; } | ||
>foo : () => { x: number; } | ||
>x : number | ||
>[] : undefined[] | ||
|
||
var p = foo().x; | ||
>p : number | ||
>foo().x : number | ||
>foo() : { x: number; } | ||
>foo : () => { x: number; } | ||
>x : number | ||
} | ||
} |
Oops, something went wrong.
since you may use
declaration.parent.parent
, I would prefervar forOf = declaration.parent.parent