mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 02:33:53 -06:00
In ES6, an Iterable should contextually type an array literal
This commit is contained in:
parent
c00a264bb7
commit
f3543b718f
@ -5461,7 +5461,9 @@ module ts {
|
||||
var type = getContextualType(arrayLiteral);
|
||||
if (type) {
|
||||
var index = indexOf(arrayLiteral.elements, node);
|
||||
return getTypeOfPropertyOfContextualType(type, "" + index) || getIndexTypeOfContextualType(type, IndexKind.Number);
|
||||
return getTypeOfPropertyOfContextualType(type, "" + index)
|
||||
|| getIndexTypeOfContextualType(type, IndexKind.Number)
|
||||
|| (languageVersion >= ScriptTarget.ES6 ? getIteratedType(type, /*expressionForError*/ undefined) : undefined);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -8770,7 +8772,14 @@ module ts {
|
||||
checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_of_statement, Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant);
|
||||
var rightType = checkExpression(node.expression);
|
||||
var iteratedType = getIteratedType(rightType, node.expression);
|
||||
checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined);
|
||||
|
||||
// iteratedType will be undefined if the rightType was missing properties/signatures
|
||||
// required to get it's 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.
|
||||
if (iteratedType) {
|
||||
checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined);
|
||||
}
|
||||
}
|
||||
|
||||
checkSourceElement(node.statement);
|
||||
@ -8828,15 +8837,22 @@ module ts {
|
||||
return anyType;
|
||||
}
|
||||
|
||||
return getIteratedType(getTypeOfExpression(forOfStatement.expression), forOfStatement.expression);
|
||||
// iteratedType will be undefined if the for-of expression type was missing properties/signatures
|
||||
// required to get it's 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 getIteratedType(getTypeOfExpression(forOfStatement.expression), forOfStatement.expression) || anyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* When expressionForError is undefined, it means we should not report any errors.
|
||||
*/
|
||||
function getIteratedType(iterable: Type, expressionForError: Expression): Type {
|
||||
Debug.assert(languageVersion >= ScriptTarget.ES6);
|
||||
var iteratedType = getIteratedTypeSubroutine(iterable, expressionForError);
|
||||
// Now even though we have extracted the iteratedType, we will have to validate that the type
|
||||
// passed in is actually an Iterable.
|
||||
if (iteratedType !== unknownType) {
|
||||
if (expressionForError && iteratedType) {
|
||||
var completeIterableType = globalIterableType !== emptyObjectType ? createTypeReference(<GenericType>globalIterableType, [iteratedType]) : emptyObjectType;
|
||||
checkTypeAssignableTo(iterable, completeIterableType, expressionForError);
|
||||
}
|
||||
@ -8845,7 +8861,7 @@ module ts {
|
||||
|
||||
function getIteratedTypeSubroutine(iterable: Type, expressionForError: Expression) {
|
||||
if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) {
|
||||
return iterable; // any or unknown
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// We want to treat type as an iterable, and get the type it is an iterable of. The iterable
|
||||
@ -8867,40 +8883,46 @@ module ts {
|
||||
// of signatures, we union the return types of all the signatures.
|
||||
var iteratorFunction = getTypeOfPropertyOfType(iterable, getPropertyNameForKnownSymbolName("iterator"));
|
||||
if (iteratorFunction && allConstituentTypesHaveKind(iteratorFunction, TypeFlags.Any)) {
|
||||
return iteratorFunction; // any or unknown
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var iteratorFunctionSignatures = iteratorFunction ? getSignaturesOfType(iteratorFunction, SignatureKind.Call) : emptyArray;
|
||||
if (iteratorFunctionSignatures.length === 0) {
|
||||
error(expressionForError, Diagnostics.The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator);
|
||||
return unknownType;
|
||||
if (expressionForError) {
|
||||
error(expressionForError, Diagnostics.The_right_hand_side_of_a_for_of_statement_must_have_a_Symbol_iterator_method_that_returns_an_iterator);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var iterator = getUnionType(map(iteratorFunctionSignatures, getReturnTypeOfSignature));
|
||||
if (allConstituentTypesHaveKind(iterator, TypeFlags.Any)) {
|
||||
return iterator; // any or unknown
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var iteratorNextFunction = getTypeOfPropertyOfType(iterator, "next");
|
||||
if (iteratorNextFunction && allConstituentTypesHaveKind(iteratorNextFunction, TypeFlags.Any)) {
|
||||
return iteratorNextFunction; // any or unknown
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var iteratorNextFunctionSignatures = iteratorNextFunction ? getSignaturesOfType(iteratorNextFunction, SignatureKind.Call) : emptyArray;
|
||||
if (iteratorNextFunctionSignatures.length === 0) {
|
||||
error(expressionForError, Diagnostics.The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method);
|
||||
return unknownType;
|
||||
if (expressionForError) {
|
||||
error(expressionForError, Diagnostics.The_iterator_returned_by_the_right_hand_side_of_a_for_of_statement_must_have_a_next_method);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var iteratorNextResult = getUnionType(map(iteratorNextFunctionSignatures, getReturnTypeOfSignature));
|
||||
if (allConstituentTypesHaveKind(iteratorNextResult, TypeFlags.Any)) {
|
||||
return iteratorNextResult; // any or unknown
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value");
|
||||
if (!iteratorNextValue) {
|
||||
error(expressionForError, Diagnostics.The_object_returned_by_the_next_method_of_the_iterator_must_have_a_value_property);
|
||||
return unknownType;
|
||||
if (expressionForError) {
|
||||
error(expressionForError, Diagnostics.The_object_returned_by_the_next_method_of_the_iterator_must_have_a_value_property);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return iteratorNextValue;
|
||||
|
||||
11
tests/baselines/reference/for-of36.js
Normal file
11
tests/baselines/reference/for-of36.js
Normal file
@ -0,0 +1,11 @@
|
||||
//// [for-of36.ts]
|
||||
var tuple: [string, boolean] = ["", true];
|
||||
for (var v of tuple) {
|
||||
v;
|
||||
}
|
||||
|
||||
//// [for-of36.js]
|
||||
var tuple = ["", true];
|
||||
for (var v of tuple) {
|
||||
v;
|
||||
}
|
||||
12
tests/baselines/reference/for-of36.types
Normal file
12
tests/baselines/reference/for-of36.types
Normal file
@ -0,0 +1,12 @@
|
||||
=== tests/cases/conformance/es6/for-ofStatements/for-of36.ts ===
|
||||
var tuple: [string, boolean] = ["", true];
|
||||
>tuple : [string, boolean]
|
||||
>["", true] : [string, boolean]
|
||||
|
||||
for (var v of tuple) {
|
||||
>v : string | boolean
|
||||
>tuple : [string, boolean]
|
||||
|
||||
v;
|
||||
>v : string | boolean
|
||||
}
|
||||
11
tests/baselines/reference/for-of37.js
Normal file
11
tests/baselines/reference/for-of37.js
Normal file
@ -0,0 +1,11 @@
|
||||
//// [for-of37.ts]
|
||||
var map = new Map([["", true]]);
|
||||
for (var v of map) {
|
||||
v;
|
||||
}
|
||||
|
||||
//// [for-of37.js]
|
||||
var map = new Map([["", true]]);
|
||||
for (var v of map) {
|
||||
v;
|
||||
}
|
||||
15
tests/baselines/reference/for-of37.types
Normal file
15
tests/baselines/reference/for-of37.types
Normal file
@ -0,0 +1,15 @@
|
||||
=== tests/cases/conformance/es6/for-ofStatements/for-of37.ts ===
|
||||
var map = new Map([["", true]]);
|
||||
>map : Map<string, boolean>
|
||||
>new Map([["", true]]) : Map<string, boolean>
|
||||
>Map : MapConstructor
|
||||
>[["", true]] : [string, boolean][]
|
||||
>["", true] : [string, boolean]
|
||||
|
||||
for (var v of map) {
|
||||
>v : [string, boolean]
|
||||
>map : Map<string, boolean>
|
||||
|
||||
v;
|
||||
>v : [string, boolean]
|
||||
}
|
||||
5
tests/baselines/reference/iterableContextualTyping1.js
Normal file
5
tests/baselines/reference/iterableContextualTyping1.js
Normal file
@ -0,0 +1,5 @@
|
||||
//// [iterableContextualTyping1.ts]
|
||||
var iter: Iterable<(x: string) => number> = [s => s.length];
|
||||
|
||||
//// [iterableContextualTyping1.js]
|
||||
var iter = [s => s.length];
|
||||
12
tests/baselines/reference/iterableContextualTyping1.types
Normal file
12
tests/baselines/reference/iterableContextualTyping1.types
Normal file
@ -0,0 +1,12 @@
|
||||
=== tests/cases/conformance/expressions/contextualTyping/iterableContextualTyping1.ts ===
|
||||
var iter: Iterable<(x: string) => number> = [s => s.length];
|
||||
>iter : Iterable<(x: string) => number>
|
||||
>Iterable : Iterable<T>
|
||||
>x : string
|
||||
>[s => s.length] : ((s: string) => number)[]
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
5
tests/cases/conformance/es6/for-ofStatements/for-of36.ts
Normal file
5
tests/cases/conformance/es6/for-ofStatements/for-of36.ts
Normal file
@ -0,0 +1,5 @@
|
||||
//@target: ES6
|
||||
var tuple: [string, boolean] = ["", true];
|
||||
for (var v of tuple) {
|
||||
v;
|
||||
}
|
||||
5
tests/cases/conformance/es6/for-ofStatements/for-of37.ts
Normal file
5
tests/cases/conformance/es6/for-ofStatements/for-of37.ts
Normal file
@ -0,0 +1,5 @@
|
||||
//@target: ES6
|
||||
var map = new Map([["", true]]);
|
||||
for (var v of map) {
|
||||
v;
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
//@target: ES6
|
||||
var iter: Iterable<(x: string) => number> = [s => s.length];
|
||||
Loading…
x
Reference in New Issue
Block a user