@@ -4117,7 +4117,7 @@ namespace ts {
41174117 // This elementType will be used if the specific property corresponding to this index is not
41184118 // present (aka the tuple element property). This call also checks that the parentType is in
41194119 // fact an iterable or array (depending on target language).
4120- const elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false, /*allowAsyncIterable */ false);
4120+ const elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false, /*allowAsyncIterables */ false);
41214121 if (declaration.dotDotDotToken) {
41224122 // Rest element has an array type with the same element type as the parent type
41234123 type = createArrayType(elementType);
@@ -10888,12 +10888,12 @@ namespace ts {
1088810888
1088910889 function getTypeOfDestructuredArrayElement(type: Type, index: number) {
1089010890 return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index) ||
10891- checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterable */ false) ||
10891+ checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables */ false) ||
1089210892 unknownType;
1089310893 }
1089410894
1089510895 function getTypeOfDestructuredSpreadExpression(type: Type) {
10896- return createArrayType(checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterable */ false) || unknownType);
10896+ return createArrayType(checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables */ false) || unknownType);
1089710897 }
1089810898
1089910899 function getAssignedTypeOfBinaryExpression(node: BinaryExpression): Type {
@@ -12867,7 +12867,7 @@ namespace ts {
1286712867 const index = indexOf(arrayLiteral.elements, node);
1286812868 return getTypeOfPropertyOfContextualType(type, "" + index)
1286912869 || getIndexTypeOfContextualType(type, IndexKind.Number)
12870- || getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterable */ false, /*checkAssignability*/ false);
12870+ || getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables */ false, /*checkAssignability*/ false);
1287112871 }
1287212872 return undefined;
1287312873 }
@@ -13105,7 +13105,7 @@ namespace ts {
1310513105 }
1310613106
1310713107 const arrayOrIterableType = checkExpression(node.expression, checkMode);
13108- return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false, /*allowAsyncIterable */ false);
13108+ return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false, /*allowAsyncIterables */ false);
1310913109 }
1311013110
1311113111 function hasDefaultValue(node: BindingElement | Expression): boolean {
@@ -13134,7 +13134,7 @@ namespace ts {
1313413134 // if there is no index type / iterated type.
1313513135 const restArrayType = checkExpression((<SpreadElement>e).expression, checkMode);
1313613136 const restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) ||
13137- getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterable */ false, /*checkAssignability*/ false);
13137+ getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables */ false, /*checkAssignability*/ false);
1313813138 if (restElementType) {
1313913139 elementTypes.push(restElementType);
1314013140 }
@@ -16987,7 +16987,7 @@ namespace ts {
1698716987 // This elementType will be used if the specific property corresponding to this index is not
1698816988 // present (aka the tuple element property). This call also checks that the parentType is in
1698916989 // fact an iterable or array (depending on target language).
16990- const elementType = checkIteratedTypeOrElementType(sourceType, node, /*allowStringInput*/ false, /*allowAsyncIterable */ false) || unknownType;
16990+ const elementType = checkIteratedTypeOrElementType(sourceType, node, /*allowStringInput*/ false, /*allowAsyncIterables */ false) || unknownType;
1699116991 const elements = node.elements;
1699216992 for (let i = 0; i < elements.length; i++) {
1699316993 checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, elementType, checkMode);
@@ -20131,29 +20131,29 @@ namespace ts {
2013120131 return checkIteratedTypeOrElementType(expressionType, rhsExpression, /*allowStringInput*/ true, awaitModifier !== undefined);
2013220132 }
2013320133
20134- function checkIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean, allowAsyncIterable : boolean): Type {
20134+ function checkIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean, allowAsyncIterables : boolean): Type {
2013520135 if (isTypeAny(inputType)) {
2013620136 return inputType;
2013720137 }
2013820138
20139- return getIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterable , /*checkAssignability*/ true) || anyType;
20139+ return getIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterables , /*checkAssignability*/ true) || anyType;
2014020140 }
2014120141
2014220142 /**
2014320143 * When consuming an iterable type in a for..of, spread, or iterator destructuring assignment
2014420144 * we want to get the iterated type of an iterable for ES2015 or later, or the iterated type
2014520145 * of a iterable (if defined globally) or element type of an array like for ES2015 or earlier.
2014620146 */
20147- function getIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean, allowAsyncIterable : boolean, checkAssignability: boolean): Type {
20147+ function getIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean, allowAsyncIterables : boolean, checkAssignability: boolean): Type {
2014820148 const uplevelIteration = languageVersion >= ScriptTarget.ES2015;
2014920149 const downlevelIteration = !uplevelIteration && compilerOptions.downlevelIteration;
2015020150
2015120151 // Get the iterated type of an `Iterable<T>` or `IterableIterator<T>` only in ES2015
2015220152 // or higher, when inside of an async generator or for-await-if, or when
2015320153 // downlevelIteration is requested.
20154- if (uplevelIteration || downlevelIteration || allowAsyncIterable ) {
20154+ if (uplevelIteration || downlevelIteration || allowAsyncIterables ) {
2015520155 // We only report errors for an invalid iterable type in ES2015 or higher.
20156- const iteratedType = getIteratedTypeOfIterable(inputType, uplevelIteration ? errorNode : undefined, allowAsyncIterable, allowAsyncIterable , checkAssignability);
20156+ const iteratedType = getIteratedTypeOfIterable(inputType, uplevelIteration ? errorNode : undefined, allowAsyncIterables, /*allowSyncIterables*/ true , checkAssignability);
2015720157 if (iteratedType || uplevelIteration) {
2015820158 return iteratedType;
2015920159 }
@@ -20267,79 +20267,75 @@ namespace ts {
2026720267 * For a **for-await-of** statement or a `yield*` in an async generator we will look for
2026820268 * the `[Symbol.asyncIterator]()` method first, and then the `[Symbol.iterator]()` method.
2026920269 */
20270- function getIteratedTypeOfIterable(type: Type, errorNode: Node | undefined, isAsyncIterable : boolean, allowNonAsyncIterables : boolean, checkAssignability: boolean): Type | undefined {
20270+ function getIteratedTypeOfIterable(type: Type, errorNode: Node | undefined, allowAsyncIterables : boolean, allowSyncIterables : boolean, checkAssignability: boolean): Type | undefined {
2027120271 if (isTypeAny(type)) {
2027220272 return undefined;
2027320273 }
2027420274
20275- const typeAsIterable = <IterableOrIteratorType>type;
20276- if (isAsyncIterable ? typeAsIterable.iteratedTypeOfAsyncIterable : typeAsIterable.iteratedTypeOfIterable) {
20277- return isAsyncIterable ? typeAsIterable.iteratedTypeOfAsyncIterable : typeAsIterable.iteratedTypeOfIterable;
20278- }
20275+ return mapType(type, getIteratedType);
20276+
20277+ function getIteratedType(type: Type) {
20278+ const typeAsIterable = <IterableOrIteratorType>type;
20279+ if (allowAsyncIterables) {
20280+ if (typeAsIterable.iteratedTypeOfAsyncIterable) {
20281+ return typeAsIterable.iteratedTypeOfAsyncIterable;
20282+ }
2027920283
20280- if (isAsyncIterable) {
20281- // As an optimization, if the type is an instantiation of the global `AsyncIterable <T>`
20282- // or the global `AsyncIterableIterator<T>` then just grab its type argument.
20283- if ( isReferenceToType(type, getGlobalAsyncIterableType (/*reportErrors*/ false)) ||
20284- isReferenceToType(type, getGlobalAsyncIterableIteratorType(/*reportErrors*/ false))) {
20285- return typeAsIterable.iteratedTypeOfAsyncIterable = (<GenericType>type).typeArguments[0];
20284+ // As an optimization, if the type is an instantiation of the global `AsyncIterable<T>`
20285+ // or the global `AsyncIterableIterator <T>` then just grab its type argument.
20286+ if (isReferenceToType(type, getGlobalAsyncIterableType(/*reportErrors*/ false)) ||
20287+ isReferenceToType(type, getGlobalAsyncIterableIteratorType (/*reportErrors*/ false))) {
20288+ return typeAsIterable.iteratedTypeOfAsyncIterable = (<GenericType>type).typeArguments[0];
20289+ }
2028620290 }
20287- }
2028820291
20289- if (!isAsyncIterable || allowNonAsyncIterables) {
20290- // As an optimization, if the type is an instantiation of the global `Iterable<T>` or
20291- // `IterableIterator<T>` then just grab its type argument.
20292- if (isReferenceToType(type, getGlobalIterableType(/*reportErrors*/ false)) ||
20293- isReferenceToType(type, getGlobalIterableIteratorType(/*reportErrors*/ false))) {
20294- return isAsyncIterable
20295- ? typeAsIterable.iteratedTypeOfAsyncIterable = (<GenericType>type).typeArguments[0]
20296- : typeAsIterable.iteratedTypeOfIterable = (<GenericType>type).typeArguments[0];
20292+ if (allowSyncIterables) {
20293+ if (typeAsIterable.iteratedTypeOfIterable) {
20294+ return typeAsIterable.iteratedTypeOfIterable;
20295+ }
20296+
20297+ // As an optimization, if the type is an instantiation of the global `Iterable<T>` or
20298+ // `IterableIterator<T>` then just grab its type argument.
20299+ if (isReferenceToType(type, getGlobalIterableType(/*reportErrors*/ false)) ||
20300+ isReferenceToType(type, getGlobalIterableIteratorType(/*reportErrors*/ false))) {
20301+ return typeAsIterable.iteratedTypeOfIterable = (<GenericType>type).typeArguments[0];
20302+ }
2029720303 }
20298- }
2029920304
20300- let iteratorMethodSignatures: Signature[];
20301- let isNonAsyncIterable = false;
20302- if (isAsyncIterable) {
20303- const iteratorMethod = getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("asyncIterator"));
20304- if (isTypeAny(iteratorMethod)) {
20305+ const asyncMethodType = allowAsyncIterables && getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("asyncIterator"));
20306+ const methodType = asyncMethodType || (allowSyncIterables && getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("iterator")));
20307+ if (isTypeAny(methodType)) {
2030520308 return undefined;
2030620309 }
20307- iteratorMethodSignatures = iteratorMethod && getSignaturesOfType(iteratorMethod, SignatureKind.Call);
20308- }
2030920310
20310- if (!isAsyncIterable || (allowNonAsyncIterables && !some(iteratorMethodSignatures))) {
20311- const iteratorMethod = getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("iterator"));
20312- if (isTypeAny(iteratorMethod)) {
20311+ const signatures = methodType && getSignaturesOfType(methodType, SignatureKind.Call);
20312+ if (!some(signatures)) {
20313+ if (errorNode) {
20314+ error(errorNode,
20315+ allowAsyncIterables
20316+ ? Diagnostics.Type_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator
20317+ : Diagnostics.Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator);
20318+ // only report on the first error
20319+ errorNode = undefined;
20320+ }
2031320321 return undefined;
2031420322 }
20315- iteratorMethodSignatures = iteratorMethod && getSignaturesOfType(iteratorMethod, SignatureKind.Call);
20316- isNonAsyncIterable = true;
20317- }
2031820323
20319- if (some(iteratorMethodSignatures)) {
20320- const iteratorMethodReturnType = getUnionType(map(iteratorMethodSignatures, getReturnTypeOfSignature), /*subtypeReduction*/ true);
20321- const iteratedType = getIteratedTypeOfIterator(iteratorMethodReturnType, errorNode, /*isAsyncIterator*/ !isNonAsyncIterable);
20324+ const returnType = getUnionType(map(signatures, getReturnTypeOfSignature), /*subtypeReduction*/ true);
20325+ const iteratedType = getIteratedTypeOfIterator(returnType, errorNode, /*isAsyncIterator*/ !!asyncMethodType);
2032220326 if (checkAssignability && errorNode && iteratedType) {
2032320327 // If `checkAssignability` was specified, we were called from
2032420328 // `checkIteratedTypeOrElementType`. As such, we need to validate that
2032520329 // the type passed in is actually an Iterable.
20326- checkTypeAssignableTo(type, isNonAsyncIterable
20327- ? createIterableType (iteratedType)
20328- : createAsyncIterableType (iteratedType), errorNode);
20330+ checkTypeAssignableTo(type, asyncMethodType
20331+ ? createAsyncIterableType (iteratedType)
20332+ : createIterableType (iteratedType), errorNode);
2032920333 }
20330- return isAsyncIterable
20334+
20335+ return asyncMethodType
2033120336 ? typeAsIterable.iteratedTypeOfAsyncIterable = iteratedType
2033220337 : typeAsIterable.iteratedTypeOfIterable = iteratedType;
2033320338 }
20334-
20335- if (errorNode) {
20336- error(errorNode,
20337- isAsyncIterable
20338- ? Diagnostics.Type_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator
20339- : Diagnostics.Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator);
20340- }
20341-
20342- return undefined;
2034320339 }
2034420340
2034520341 /**
@@ -20439,7 +20435,7 @@ namespace ts {
2043920435 return undefined;
2044020436 }
2044120437
20442- return getIteratedTypeOfIterable(returnType, /*errorNode*/ undefined, isAsyncGenerator, /*allowNonAsyncIterables */ false , /*checkAssignability*/ false)
20438+ return getIteratedTypeOfIterable(returnType, /*errorNode*/ undefined, /*allowAsyncIterables*/ isAsyncGenerator, /*allowSyncIterables */ !isAsyncGenerator , /*checkAssignability*/ false)
2044320439 || getIteratedTypeOfIterator(returnType, /*errorNode*/ undefined, isAsyncGenerator);
2044420440 }
2044520441
@@ -22649,7 +22645,7 @@ namespace ts {
2264922645 Debug.assert(expr.parent.kind === SyntaxKind.ArrayLiteralExpression);
2265022646 // [{ property1: p1, property2 }] = elems;
2265122647 const typeOfArrayLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(<Expression>expr.parent);
22652- const elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || unknownType, expr.parent, /*allowStringInput*/ false, /*allowAsyncIterable */ false) || unknownType;
22648+ const elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || unknownType, expr.parent, /*allowStringInput*/ false, /*allowAsyncIterables */ false) || unknownType;
2265322649 return checkArrayLiteralDestructuringElementAssignment(<ArrayLiteralExpression>expr.parent, typeOfArrayLiteral,
2265422650 indexOf((<ArrayLiteralExpression>expr.parent).elements, expr), elementType || unknownType);
2265522651 }
0 commit comments