Fix return value and error reporting for getIterationTypesOfMethod (#50146)

This commit is contained in:
Ron Buckton
2022-08-03 19:07:29 -04:00
committed by GitHub
parent bc7786b24e
commit 6bbe6d67d1
11 changed files with 148 additions and 62 deletions
+109 -45
View File
@@ -38819,13 +38819,22 @@ namespace ts {
}
if (!(type.flags & TypeFlags.Union)) {
const iterationTypes = getIterationTypesOfIterableWorker(type, use, errorNode);
const errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined = errorNode ? { errors: undefined } : undefined;
const iterationTypes = getIterationTypesOfIterableWorker(type, use, errorNode, errorOutputContainer);
if (iterationTypes === noIterationTypes) {
if (errorNode) {
reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag));
const rootDiag = reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag));
if (errorOutputContainer?.errors) {
addRelatedInfo(rootDiag, ...errorOutputContainer.errors);
}
}
return undefined;
}
else if (errorOutputContainer?.errors?.length) {
for (const diag of errorOutputContainer.errors) {
diagnostics.add(diag);
}
}
return iterationTypes;
}
@@ -38835,17 +38844,25 @@ namespace ts {
let allIterationTypes: IterationTypes[] | undefined;
for (const constituent of (type as UnionType).types) {
const iterationTypes = getIterationTypesOfIterableWorker(constituent, use, errorNode);
const errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined = errorNode ? { errors: undefined } : undefined;
const iterationTypes = getIterationTypesOfIterableWorker(constituent, use, errorNode, errorOutputContainer);
if (iterationTypes === noIterationTypes) {
if (errorNode) {
reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag));
const rootDiag = reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag));
if (errorOutputContainer?.errors) {
addRelatedInfo(rootDiag, ...errorOutputContainer.errors);
}
}
setCachedIterationTypes(type, cacheKey, noIterationTypes);
return undefined;
}
else {
allIterationTypes = append(allIterationTypes, iterationTypes);
else if (errorOutputContainer?.errors?.length) {
for (const diag of errorOutputContainer.errors) {
diagnostics.add(diag);
}
}
allIterationTypes = append(allIterationTypes, iterationTypes);
}
const iterationTypes = allIterationTypes ? combineIterationTypes(allIterationTypes) : noIterationTypes;
@@ -38877,53 +38894,69 @@ namespace ts {
* NOTE: You probably don't want to call this directly and should be calling
* `getIterationTypesOfIterable` instead.
*/
function getIterationTypesOfIterableWorker(type: Type, use: IterationUse, errorNode: Node | undefined) {
function getIterationTypesOfIterableWorker(type: Type, use: IterationUse, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined) {
if (isTypeAny(type)) {
return anyIterationTypes;
}
// If we are reporting errors and encounter a cached `noIterationTypes`, we should ignore the cached value and continue as if nothing was cached.
// In addition, we should not cache any new results for this call.
let noCache = false;
if (use & IterationUse.AllowsAsyncIterablesFlag) {
const iterationTypes =
getIterationTypesOfIterableCached(type, asyncIterationTypesResolver) ||
getIterationTypesOfIterableFast(type, asyncIterationTypesResolver);
if (iterationTypes) {
return use & IterationUse.ForOfFlag ?
getAsyncFromSyncIterationTypes(iterationTypes, errorNode) :
iterationTypes;
if (iterationTypes === noIterationTypes && errorNode) {
// ignore the cached value
noCache = true;
}
else {
return use & IterationUse.ForOfFlag ?
getAsyncFromSyncIterationTypes(iterationTypes, errorNode) :
iterationTypes;
}
}
}
if (use & IterationUse.AllowsSyncIterablesFlag) {
const iterationTypes =
let iterationTypes =
getIterationTypesOfIterableCached(type, syncIterationTypesResolver) ||
getIterationTypesOfIterableFast(type, syncIterationTypesResolver);
if (iterationTypes) {
if (use & IterationUse.AllowsAsyncIterablesFlag) {
// for a sync iterable in an async context, only use the cached types if they are valid.
if (iterationTypes !== noIterationTypes) {
return setCachedIterationTypes(type, "iterationTypesOfAsyncIterable", getAsyncFromSyncIterationTypes(iterationTypes, errorNode));
}
if (iterationTypes === noIterationTypes && errorNode) {
// ignore the cached value
noCache = true;
}
else {
return iterationTypes;
if (use & IterationUse.AllowsAsyncIterablesFlag) {
// for a sync iterable in an async context, only use the cached types if they are valid.
if (iterationTypes !== noIterationTypes) {
iterationTypes = getAsyncFromSyncIterationTypes(iterationTypes, errorNode);
return noCache ? iterationTypes : setCachedIterationTypes(type, "iterationTypesOfAsyncIterable", iterationTypes);
}
}
else {
return iterationTypes;
}
}
}
}
if (use & IterationUse.AllowsAsyncIterablesFlag) {
const iterationTypes = getIterationTypesOfIterableSlow(type, asyncIterationTypesResolver, errorNode);
const iterationTypes = getIterationTypesOfIterableSlow(type, asyncIterationTypesResolver, errorNode, errorOutputContainer, noCache);
if (iterationTypes !== noIterationTypes) {
return iterationTypes;
}
}
if (use & IterationUse.AllowsSyncIterablesFlag) {
const iterationTypes = getIterationTypesOfIterableSlow(type, syncIterationTypesResolver, errorNode);
let iterationTypes = getIterationTypesOfIterableSlow(type, syncIterationTypesResolver, errorNode, errorOutputContainer, noCache);
if (iterationTypes !== noIterationTypes) {
if (use & IterationUse.AllowsAsyncIterablesFlag) {
return setCachedIterationTypes(type, "iterationTypesOfAsyncIterable", iterationTypes
? getAsyncFromSyncIterationTypes(iterationTypes, errorNode)
: noIterationTypes);
iterationTypes = getAsyncFromSyncIterationTypes(iterationTypes, errorNode);
return noCache ? iterationTypes : setCachedIterationTypes(type, "iterationTypesOfAsyncIterable", iterationTypes);
}
else {
return iterationTypes;
@@ -38948,7 +38981,7 @@ namespace ts {
function getIterationTypesOfGlobalIterableType(globalType: Type, resolver: IterationTypesResolver) {
const globalIterationTypes =
getIterationTypesOfIterableCached(globalType, resolver) ||
getIterationTypesOfIterableSlow(globalType, resolver, /*errorNode*/ undefined);
getIterationTypesOfIterableSlow(globalType, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined, /*noCache*/ false);
return globalIterationTypes === noIterationTypes ? defaultIterationTypes : globalIterationTypes;
}
@@ -39006,28 +39039,28 @@ namespace ts {
* NOTE: You probably don't want to call this directly and should be calling
* `getIterationTypesOfIterable` instead.
*/
function getIterationTypesOfIterableSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined) {
function getIterationTypesOfIterableSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined, noCache: boolean) {
const method = getPropertyOfType(type, getPropertyNameForKnownSymbolName(resolver.iteratorSymbolName));
const methodType = method && !(method.flags & SymbolFlags.Optional) ? getTypeOfSymbol(method) : undefined;
if (isTypeAny(methodType)) {
return setCachedIterationTypes(type, resolver.iterableCacheKey, anyIterationTypes);
return noCache ? anyIterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, anyIterationTypes);
}
const signatures = methodType ? getSignaturesOfType(methodType, SignatureKind.Call) : undefined;
if (!some(signatures)) {
return setCachedIterationTypes(type, resolver.iterableCacheKey, noIterationTypes);
return noCache ? noIterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, noIterationTypes);
}
const iteratorType = getIntersectionType(map(signatures, getReturnTypeOfSignature));
const iterationTypes = getIterationTypesOfIterator(iteratorType, resolver, errorNode) ?? noIterationTypes;
return setCachedIterationTypes(type, resolver.iterableCacheKey, iterationTypes);
const iterationTypes = getIterationTypesOfIteratorWorker(iteratorType, resolver, errorNode, errorOutputContainer, noCache) ?? noIterationTypes;
return noCache ? iterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, iterationTypes);
}
function reportTypeNotIterableError(errorNode: Node, type: Type, allowAsyncIterables: boolean): void {
function reportTypeNotIterableError(errorNode: Node, type: Type, allowAsyncIterables: boolean): Diagnostic {
const message = allowAsyncIterables
? Diagnostics.Type_0_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator
: Diagnostics.Type_0_must_have_a_Symbol_iterator_method_that_returns_an_iterator;
errorAndMaybeSuggestAwait(errorNode, !!getAwaitedTypeOfPromise(type), message, typeToString(type));
return errorAndMaybeSuggestAwait(errorNode, !!getAwaitedTypeOfPromise(type), message, typeToString(type));
}
/**
@@ -39036,15 +39069,34 @@ namespace ts {
* If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes`
* record is returned. Otherwise, `undefined` is returned.
*/
function getIterationTypesOfIterator(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined) {
function getIterationTypesOfIterator(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined) {
return getIterationTypesOfIteratorWorker(type, resolver, errorNode, errorOutputContainer, /*noCache*/ false);
}
/**
* Gets the *yield*, *return*, and *next* types from an `Iterator`-like or `AsyncIterator`-like type.
*
* If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes`
* record is returned. Otherwise, `undefined` is returned.
*
* NOTE: You probably don't want to call this directly and should be calling
* `getIterationTypesOfIterator` instead.
*/
function getIterationTypesOfIteratorWorker(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined, noCache: boolean) {
if (isTypeAny(type)) {
return anyIterationTypes;
}
const iterationTypes =
let iterationTypes =
getIterationTypesOfIteratorCached(type, resolver) ||
getIterationTypesOfIteratorFast(type, resolver) ||
getIterationTypesOfIteratorSlow(type, resolver, errorNode);
getIterationTypesOfIteratorFast(type, resolver);
if (iterationTypes === noIterationTypes && errorNode) {
iterationTypes = undefined;
noCache = true;
}
iterationTypes ??= getIterationTypesOfIteratorSlow(type, resolver, errorNode, errorOutputContainer, noCache);
return iterationTypes === noIterationTypes ? undefined : iterationTypes;
}
@@ -39085,7 +39137,7 @@ namespace ts {
// and `undefined` in our libs by default, a custom lib *could* use different definitions.
const globalIterationTypes =
getIterationTypesOfIteratorCached(globalType, resolver) ||
getIterationTypesOfIteratorSlow(globalType, resolver, /*errorNode*/ undefined);
getIterationTypesOfIteratorSlow(globalType, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined, /*noCache*/ false);
const { returnType, nextType } = globalIterationTypes === noIterationTypes ? defaultIterationTypes : globalIterationTypes;
return setCachedIterationTypes(type, resolver.iteratorCacheKey, createIterationTypes(yieldType, returnType, nextType));
}
@@ -39166,7 +39218,7 @@ namespace ts {
* If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes`
* record is returned. Otherwise, we return `undefined`.
*/
function getIterationTypesOfMethod(type: Type, resolver: IterationTypesResolver, methodName: "next" | "return" | "throw", errorNode: Node | undefined): IterationTypes | undefined {
function getIterationTypesOfMethod(type: Type, resolver: IterationTypesResolver, methodName: "next" | "return" | "throw", errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined): IterationTypes | undefined {
const method = getPropertyOfType(type, methodName as __String);
// Ignore 'return' or 'throw' if they are missing.
@@ -39190,9 +39242,15 @@ namespace ts {
const diagnostic = methodName === "next"
? resolver.mustHaveANextMethodDiagnostic
: resolver.mustBeAMethodDiagnostic;
error(errorNode, diagnostic, methodName);
if (errorOutputContainer) {
errorOutputContainer.errors ??= [];
errorOutputContainer.errors.push(createDiagnosticForNode(errorNode, diagnostic, methodName));
}
else {
error(errorNode, diagnostic, methodName);
}
}
return methodName === "next" ? anyIterationTypes : undefined;
return methodName === "next" ? noIterationTypes : undefined;
}
// If the method signature comes exclusively from the global iterator or generator type,
@@ -39251,7 +39309,13 @@ namespace ts {
const iterationTypes = getIterationTypesOfIteratorResult(resolvedMethodReturnType);
if (iterationTypes === noIterationTypes) {
if (errorNode) {
error(errorNode, resolver.mustHaveAValueDiagnostic, methodName);
if (errorOutputContainer) {
errorOutputContainer.errors ??= [];
errorOutputContainer.errors.push(createDiagnosticForNode(errorNode, resolver.mustHaveAValueDiagnostic, methodName));
}
else {
error(errorNode, resolver.mustHaveAValueDiagnostic, methodName);
}
}
yieldType = anyType;
returnTypes = append(returnTypes, anyType);
@@ -39274,13 +39338,13 @@ namespace ts {
* NOTE: You probably don't want to call this directly and should be calling
* `getIterationTypesOfIterator` instead.
*/
function getIterationTypesOfIteratorSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined) {
function getIterationTypesOfIteratorSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined, noCache: boolean) {
const iterationTypes = combineIterationTypes([
getIterationTypesOfMethod(type, resolver, "next", errorNode),
getIterationTypesOfMethod(type, resolver, "return", errorNode),
getIterationTypesOfMethod(type, resolver, "throw", errorNode),
getIterationTypesOfMethod(type, resolver, "next", errorNode, errorOutputContainer),
getIterationTypesOfMethod(type, resolver, "return", errorNode, errorOutputContainer),
getIterationTypesOfMethod(type, resolver, "throw", errorNode, errorOutputContainer),
]);
return setCachedIterationTypes(type, resolver.iteratorCacheKey, iterationTypes);
return noCache ? iterationTypes : setCachedIterationTypes(type, resolver.iteratorCacheKey, iterationTypes);
}
/**
@@ -39305,7 +39369,7 @@ namespace ts {
const use = isAsyncGenerator ? IterationUse.AsyncGeneratorReturnType : IterationUse.GeneratorReturnType;
const resolver = isAsyncGenerator ? asyncIterationTypesResolver : syncIterationTypesResolver;
return getIterationTypesOfIterable(type, use, /*errorNode*/ undefined) ||
getIterationTypesOfIterator(type, resolver, /*errorNode*/ undefined);
getIterationTypesOfIterator(type, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined);
}
function checkBreakOrContinueStatement(node: BreakOrContinueStatement) {
+10 -3
View File
@@ -1,7 +1,8 @@
tests/cases/conformance/es6/for-ofStatements/for-of16.ts(8,11): error TS2489: An iterator must have a 'next()' method.
tests/cases/conformance/es6/for-ofStatements/for-of16.ts(8,11): error TS2488: Type 'StringIterator' must have a '[Symbol.iterator]()' method that returns an iterator.
tests/cases/conformance/es6/for-ofStatements/for-of16.ts(10,11): error TS2488: Type 'StringIterator' must have a '[Symbol.iterator]()' method that returns an iterator.
==== tests/cases/conformance/es6/for-ofStatements/for-of16.ts (1 errors) ====
==== tests/cases/conformance/es6/for-ofStatements/for-of16.ts (2 errors) ====
class StringIterator {
[Symbol.iterator]() {
return this;
@@ -11,4 +12,10 @@ tests/cases/conformance/es6/for-ofStatements/for-of16.ts(8,11): error TS2489: An
var v: string;
for (v of new StringIterator) { } // Should fail
~~~~~~~~~~~~~~~~~~
!!! error TS2489: An iterator must have a 'next()' method.
!!! error TS2488: Type 'StringIterator' must have a '[Symbol.iterator]()' method that returns an iterator.
!!! related TS2489 tests/cases/conformance/es6/for-ofStatements/for-of16.ts:8:11: An iterator must have a 'next()' method.
for (v of new StringIterator) { } // Should still fail (related errors should still be shown even though type is cached).
~~~~~~~~~~~~~~~~~~
!!! error TS2488: Type 'StringIterator' must have a '[Symbol.iterator]()' method that returns an iterator.
!!! related TS2489 tests/cases/conformance/es6/for-ofStatements/for-of16.ts:10:11: An iterator must have a 'next()' method.
+4 -1
View File
@@ -6,7 +6,9 @@ class StringIterator {
}
var v: string;
for (v of new StringIterator) { } // Should fail
for (v of new StringIterator) { } // Should fail
for (v of new StringIterator) { } // Should still fail (related errors should still be shown even though type is cached).
//// [for-of16.js]
class StringIterator {
@@ -16,3 +18,4 @@ class StringIterator {
}
var v;
for (v of new StringIterator) { } // Should fail
for (v of new StringIterator) { } // Should still fail (related errors should still be shown even though type is cached).
@@ -20,3 +20,7 @@ for (v of new StringIterator) { } // Should fail
>v : Symbol(v, Decl(for-of16.ts, 6, 3))
>StringIterator : Symbol(StringIterator, Decl(for-of16.ts, 0, 0))
for (v of new StringIterator) { } // Should still fail (related errors should still be shown even though type is cached).
>v : Symbol(v, Decl(for-of16.ts, 6, 3))
>StringIterator : Symbol(StringIterator, Decl(for-of16.ts, 0, 0))
+5
View File
@@ -21,3 +21,8 @@ for (v of new StringIterator) { } // Should fail
>new StringIterator : StringIterator
>StringIterator : typeof StringIterator
for (v of new StringIterator) { } // Should still fail (related errors should still be shown even though type is cached).
>v : string
>new StringIterator : StringIterator
>StringIterator : typeof StringIterator
@@ -1,5 +1,5 @@
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck31.ts(2,11): error TS2322: Type 'Generator<(x: any) => any, void, any>' is not assignable to type '() => Iterable<(x: string) => number>'.
Type 'Generator<(x: any) => any, void, any>' provides no match for the signature '(): Iterable<(x: string) => number>'.
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck31.ts(2,11): error TS2322: Type 'Generator<(x: any) => any, void, unknown>' is not assignable to type '() => Iterable<(x: string) => number>'.
Type 'Generator<(x: any) => any, void, unknown>' provides no match for the signature '(): Iterable<(x: string) => number>'.
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck31.ts (1 errors) ====
@@ -10,6 +10,6 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck31.ts(2,11): erro
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} ()
~~~~~~~~
!!! error TS2322: Type 'Generator<(x: any) => any, void, any>' is not assignable to type '() => Iterable<(x: string) => number>'.
!!! error TS2322: Type 'Generator<(x: any) => any, void, any>' provides no match for the signature '(): Iterable<(x: string) => number>'.
!!! error TS2322: Type 'Generator<(x: any) => any, void, unknown>' is not assignable to type '() => Iterable<(x: string) => number>'.
!!! error TS2322: Type 'Generator<(x: any) => any, void, unknown>' provides no match for the signature '(): Iterable<(x: string) => number>'.
}
@@ -5,8 +5,8 @@ function* g2(): Iterator<() => Iterable<(x: string) => number>> {
yield function* () {
>yield function* () { yield x => x.length; } () : undefined
>function* () { yield x => x.length; } () : Generator<(x: any) => any, void, any>
>function* () { yield x => x.length; } : () => Generator<(x: any) => any, void, any>
>function* () { yield x => x.length; } () : Generator<(x: any) => any, void, unknown>
>function* () { yield x => x.length; } : () => Generator<(x: any) => any, void, unknown>
yield x => x.length;
>yield x => x.length : any
@@ -1,7 +1,7 @@
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck6.ts(1,17): error TS2322: Type 'Generator<any, any, any>' is not assignable to type 'number'.
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck6.ts(1,17): error TS2322: Type 'Generator<any, any, unknown>' is not assignable to type 'number'.
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck6.ts (1 errors) ====
function* g1(): number { }
~~~~~~
!!! error TS2322: Type 'Generator<any, any, any>' is not assignable to type 'number'.
!!! error TS2322: Type 'Generator<any, any, unknown>' is not assignable to type 'number'.
@@ -1,4 +1,4 @@
tests/cases/conformance/es6/spread/iteratorSpreadInArray10.ts(7,17): error TS2489: An iterator must have a 'next()' method.
tests/cases/conformance/es6/spread/iteratorSpreadInArray10.ts(7,17): error TS2488: Type 'SymbolIterator' must have a '[Symbol.iterator]()' method that returns an iterator.
==== tests/cases/conformance/es6/spread/iteratorSpreadInArray10.ts (1 errors) ====
@@ -10,4 +10,5 @@ tests/cases/conformance/es6/spread/iteratorSpreadInArray10.ts(7,17): error TS248
var array = [...new SymbolIterator];
~~~~~~~~~~~~~~~~~~
!!! error TS2489: An iterator must have a 'next()' method.
!!! error TS2488: Type 'SymbolIterator' must have a '[Symbol.iterator]()' method that returns an iterator.
!!! related TS2489 tests/cases/conformance/es6/spread/iteratorSpreadInArray10.ts:7:17: An iterator must have a 'next()' method.
@@ -36,7 +36,7 @@ tests/cases/conformance/types/asyncGenerators/types.asyncGenerators.es2018.2.ts(
tests/cases/conformance/types/asyncGenerators/types.asyncGenerators.es2018.2.ts(59,12): error TS2322: Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/asyncGenerators/types.asyncGenerators.es2018.2.ts(62,12): error TS2322: Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/asyncGenerators/types.asyncGenerators.es2018.2.ts(64,42): error TS2741: Property '[Symbol.iterator]' is missing in type 'AsyncGenerator<number, any, undefined>' but required in type 'IterableIterator<number>'.
tests/cases/conformance/types/asyncGenerators/types.asyncGenerators.es2018.2.ts(67,42): error TS2741: Property '[Symbol.iterator]' is missing in type 'AsyncGenerator<any, any, any>' but required in type 'Iterable<number>'.
tests/cases/conformance/types/asyncGenerators/types.asyncGenerators.es2018.2.ts(67,42): error TS2741: Property '[Symbol.iterator]' is missing in type 'AsyncGenerator<any, any, unknown>' but required in type 'Iterable<number>'.
tests/cases/conformance/types/asyncGenerators/types.asyncGenerators.es2018.2.ts(70,42): error TS2322: Type 'AsyncGenerator<number, any, undefined>' is not assignable to type 'Iterator<number, any, undefined>'.
The types returned by 'next(...)' are incompatible between these types.
Type 'Promise<IteratorResult<number, any>>' is not assignable to type 'IteratorResult<number, any>'.
@@ -173,7 +173,7 @@ tests/cases/conformance/types/asyncGenerators/types.asyncGenerators.es2018.2.ts(
}
async function * explicitReturnType11(): Iterable<number> {
~~~~~~~~~~~~~~~~
!!! error TS2741: Property '[Symbol.iterator]' is missing in type 'AsyncGenerator<any, any, any>' but required in type 'Iterable<number>'.
!!! error TS2741: Property '[Symbol.iterator]' is missing in type 'AsyncGenerator<any, any, unknown>' but required in type 'Iterable<number>'.
!!! related TS2728 /.ts/lib.es2015.iterable.d.ts:51:5: '[Symbol.iterator]' is declared here.
yield 1;
}
@@ -6,4 +6,6 @@ class StringIterator {
}
var v: string;
for (v of new StringIterator) { } // Should fail
for (v of new StringIterator) { } // Should fail
for (v of new StringIterator) { } // Should still fail (related errors should still be shown even though type is cached).