Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 5dca7cc

Browse filesBrowse files
committed
Fix yield* as well
1 parent fbd5797 commit 5dca7cc
Copy full SHA for 5dca7cc

9 files changed

+560-136Lines changed: 560 additions & 136 deletions
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+35-17Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15889,7 +15889,7 @@ namespace ts {
1588915889
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
1589015890
// return type of the body should be unwrapped to its awaited type, which we will wrap in
1589115891
// the native Promise<T> type later in this function.
15892-
type = checkAwaitedType(type, /*errorNode*/ func);
15892+
type = checkAwaitedType(type, /*errorNode*/ func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
1589315893
}
1589415894
}
1589515895
else {
@@ -15963,6 +15963,11 @@ namespace ts {
1596315963
// A yield* expression effectively yields everything that its operand yields
1596415964
type = checkIteratedTypeOrElementType(type, yieldExpression.expression, /*allowStringInput*/ false, (functionFlags & FunctionFlags.Async) !== 0);
1596515965
}
15966+
if (functionFlags & FunctionFlags.Async) {
15967+
type = checkAwaitedType(type, expr, yieldExpression.asteriskToken
15968+
? Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member
15969+
: Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
15970+
}
1596615971
if (!contains(aggregatedTypes, type)) {
1596715972
aggregatedTypes.push(type);
1596815973
}
@@ -16012,7 +16017,7 @@ namespace ts {
1601216017
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
1601316018
// return type of the body should be unwrapped to its awaited type, which should be wrapped in
1601416019
// the native Promise<T> type by the caller.
16015-
type = checkAwaitedType(type, func);
16020+
type = checkAwaitedType(type, func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
1601616021
}
1601716022
if (type.flags & TypeFlags.Never) {
1601816023
hasReturnOfTypeNever = true;
@@ -16189,7 +16194,7 @@ namespace ts {
1618916194
const exprType = checkExpression(<Expression>node.body);
1619016195
if (returnOrPromisedType) {
1619116196
if ((functionFlags & FunctionFlags.AsyncOrAsyncGenerator) === FunctionFlags.Async) { // Async function
16192-
const awaitedType = checkAwaitedType(exprType, node.body);
16197+
const awaitedType = checkAwaitedType(exprType, node.body, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
1619316198
checkTypeAssignableTo(awaitedType, returnOrPromisedType, node.body);
1619416199
}
1619516200
else { // Normal function
@@ -16305,7 +16310,7 @@ namespace ts {
1630516310
}
1630616311

1630716312
const operandType = checkExpression(node.expression);
16308-
return checkAwaitedType(operandType, node);
16313+
return checkAwaitedType(operandType, node, Diagnostics.Type_of_await_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
1630916314
}
1631016315

1631116316
function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
@@ -16952,10 +16957,22 @@ namespace ts {
1695216957
if (func.type) {
1695316958
const signatureElementType = getIteratedTypeOfGenerator(getTypeFromTypeNode(func.type), (functionFlags & FunctionFlags.Async) !== 0) || anyType;
1695416959
if (nodeIsYieldStar) {
16955-
checkTypeAssignableTo(expressionElementType, signatureElementType, node.expression, /*headMessage*/ undefined);
16960+
checkTypeAssignableTo(
16961+
functionFlags & FunctionFlags.Async
16962+
? getAwaitedType(expressionElementType, node.expression, Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)
16963+
: expressionElementType,
16964+
signatureElementType,
16965+
node.expression,
16966+
/*headMessage*/ undefined);
1695616967
}
1695716968
else {
16958-
checkTypeAssignableTo(expressionType, signatureElementType, node.expression, /*headMessage*/ undefined);
16969+
checkTypeAssignableTo(
16970+
functionFlags & FunctionFlags.Async
16971+
? getAwaitedType(expressionType, node.expression, Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)
16972+
: expressionType,
16973+
signatureElementType,
16974+
node.expression,
16975+
/*headMessage*/ undefined);
1695916976
}
1696016977
}
1696116978
}
@@ -18290,9 +18307,9 @@ namespace ts {
1829018307
}
1829118308
}
1829218309

18293-
function getAwaitedTypeOfPromise(type: Type, errorNode?: Node): Type | undefined {
18310+
function getAwaitedTypeOfPromise(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage): Type | undefined {
1829418311
const promisedType = getPromisedTypeOfPromise(type, errorNode);
18295-
return promisedType && getAwaitedType(promisedType, errorNode);
18312+
return promisedType && getAwaitedType(promisedType, errorNode, diagnosticMessage);
1829618313
}
1829718314

1829818315
/**
@@ -18360,11 +18377,11 @@ namespace ts {
1836018377
* Promise-like type; otherwise, it is the type of the expression. This is used to reflect
1836118378
* The runtime behavior of the `await` keyword.
1836218379
*/
18363-
function checkAwaitedType(type: Type, errorNode: Node): Type {
18364-
return getAwaitedType(type, errorNode) || unknownType;
18380+
function checkAwaitedType(type: Type, errorNode: Node, diagnosticMessage: DiagnosticMessage): Type {
18381+
return getAwaitedType(type, errorNode, diagnosticMessage) || unknownType;
1836518382
}
1836618383

18367-
function getAwaitedType(type: Type, errorNode?: Node): Type | undefined {
18384+
function getAwaitedType(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage): Type | undefined {
1836818385
const typeAsAwaitable = <PromiseOrAwaitableType>type;
1836918386
if (typeAsAwaitable.awaitedTypeOfType) {
1837018387
return typeAsAwaitable.awaitedTypeOfType;
@@ -18377,7 +18394,7 @@ namespace ts {
1837718394
if (type.flags & TypeFlags.Union) {
1837818395
let types: Type[];
1837918396
for (const constituentType of (<UnionType>type).types) {
18380-
types = append(types, getAwaitedType(constituentType, errorNode));
18397+
types = append(types, getAwaitedType(constituentType, errorNode, diagnosticMessage));
1838118398
}
1838218399

1838318400
if (!types) {
@@ -18431,7 +18448,7 @@ namespace ts {
1843118448
// Keep track of the type we're about to unwrap to avoid bad recursive promise types.
1843218449
// See the comments above for more information.
1843318450
awaitedTypeStack.push(type.id);
18434-
const awaitedType = getAwaitedType(promisedType, errorNode);
18451+
const awaitedType = getAwaitedType(promisedType, errorNode, diagnosticMessage);
1843518452
awaitedTypeStack.pop();
1843618453

1843718454
if (!awaitedType) {
@@ -18459,7 +18476,8 @@ namespace ts {
1845918476
const thenFunction = getTypeOfPropertyOfType(type, "then");
1846018477
if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) {
1846118478
if (errorNode) {
18462-
error(errorNode, Diagnostics.Type_used_as_operand_to_await_or_the_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
18479+
Debug.assert(!!diagnosticMessage);
18480+
error(errorNode, diagnosticMessage);
1846318481
}
1846418482
return undefined;
1846518483
}
@@ -18570,7 +18588,7 @@ namespace ts {
1857018588
}
1857118589

1857218590
// Get and return the awaited type of the return type.
18573-
return checkAwaitedType(returnType, node);
18591+
return checkAwaitedType(returnType, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
1857418592
}
1857518593

1857618594
/** Check a decorator */
@@ -19854,7 +19872,7 @@ namespace ts {
1985419872

1985519873
// For an async iterator, we must get the awaited type of the return type.
1985619874
if (isAsyncIterator) {
19857-
nextResult = getAwaitedTypeOfPromise(nextResult, errorNode);
19875+
nextResult = getAwaitedTypeOfPromise(nextResult, errorNode, Diagnostics.The_type_returned_by_the_next_method_of_an_async_iterator_must_be_a_promise_for_a_type_with_a_value_property);
1985819876
if (isTypeAny(nextResult)) {
1985919877
return undefined;
1986019878
}
@@ -19945,7 +19963,7 @@ namespace ts {
1994519963
else if (func.type || isGetAccessorWithAnnotatedSetAccessor(func)) {
1994619964
if (functionFlags & FunctionFlags.Async) { // Async function
1994719965
const promisedType = getPromisedTypeOfPromise(returnType);
19948-
const awaitedType = checkAwaitedType(exprType, node);
19966+
const awaitedType = checkAwaitedType(exprType, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
1994919967
if (promisedType) {
1995019968
// If the function has a return type, but promisedType is
1995119969
// undefined, an error will be reported in checkAsyncFunctionReturnType
Collapse file

‎src/compiler/diagnosticMessages.json‎

Copy file name to clipboardExpand all lines: src/compiler/diagnosticMessages.json
+13-1Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@
175175
"category": "Error",
176176
"code": 1057
177177
},
178-
"Type used as operand to 'await' or the return type of an async function must either be a valid promise or must not contain a callable 'then' member.": {
178+
"The return type of an async function must either be a valid promise or must not contain a callable 'then' member.": {
179179
"category": "Error",
180180
"code": 1058
181181
},
@@ -867,6 +867,18 @@
867867
"category": "Error",
868868
"code": 1319
869869
},
870+
"Type of 'await' operand must either be a valid promise or must not contain a callable 'then' member.": {
871+
"category": "Error",
872+
"code": 1320
873+
},
874+
"Type of 'yield' operand in an async generator must either be a valid promise or must not contain a callable 'then' member.": {
875+
"category": "Error",
876+
"code": 1321
877+
},
878+
"Type of iterated elements of a 'yield*' operand must either be a valid promise or must not contain a callable 'then' member.": {
879+
"category": "Error",
880+
"code": 1322
881+
},
870882
"Duplicate identifier '{0}'.": {
871883
"category": "Error",
872884
"code": 2300
Collapse file

‎tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt‎

Copy file name to clipboardExpand all lines: tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1
88
Types of property 'then' are incompatible.
99
Type '() => void' is not assignable to type '<TResult1 = any, TResult2 = never>(onfulfilled?: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => PromiseLike<TResult1 | TResult2>'.
1010
Type 'void' is not assignable to type 'PromiseLike<any>'.
11-
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(17,16): error TS1058: Type used as operand to 'await' or the return type of an async function must either be a valid promise or must not contain a callable 'then' member.
12-
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(23,25): error TS1058: Type used as operand to 'await' or the return type of an async function must either be a valid promise or must not contain a callable 'then' member.
11+
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(17,16): error TS1058: The return type of an async function must either be a valid promise or must not contain a callable 'then' member.
12+
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(23,25): error TS1320: Type of 'await' operand must either be a valid promise or must not contain a callable 'then' member.
1313

1414

1515
==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts (8 errors) ====
@@ -47,13 +47,13 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1
4747
async function fn12() { return obj; } // valid: Promise<{ then: string; }>
4848
async function fn13() { return thenable; } // error
4949
~~~~
50-
!!! error TS1058: Type used as operand to 'await' or the return type of an async function must either be a valid promise or must not contain a callable 'then' member.
50+
!!! error TS1058: The return type of an async function must either be a valid promise or must not contain a callable 'then' member.
5151
async function fn14() { await 1; } // valid: Promise<void>
5252
async function fn15() { await null; } // valid: Promise<void>
5353
async function fn16() { await undefined; } // valid: Promise<void>
5454
async function fn17() { await a; } // valid: Promise<void>
5555
async function fn18() { await obj; } // valid: Promise<void>
5656
async function fn19() { await thenable; } // error
5757
~~~~~~~~~~~~~~
58-
!!! error TS1058: Type used as operand to 'await' or the return type of an async function must either be a valid promise or must not contain a callable 'then' member.
58+
!!! error TS1320: Type of 'await' operand must either be a valid promise or must not contain a callable 'then' member.
5959

Collapse file

‎tests/baselines/reference/asyncFunctionDeclaration15_es6.errors.txt‎

Copy file name to clipboardExpand all lines: tests/baselines/reference/asyncFunctionDeclaration15_es6.errors.txt
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration1
33
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(8,23): error TS1064: The return type of an async function or method must be the global Promise<T> type.
44
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(9,23): error TS1064: The return type of an async function or method must be the global Promise<T> type.
55
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(10,23): error TS1064: The return type of an async function or method must be the global Promise<T> type.
6-
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(17,16): error TS1058: Type used as operand to 'await' or the return type of an async function must either be a valid promise or must not contain a callable 'then' member.
7-
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(23,25): error TS1058: Type used as operand to 'await' or the return type of an async function must either be a valid promise or must not contain a callable 'then' member.
6+
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(17,16): error TS1058: The return type of an async function must either be a valid promise or must not contain a callable 'then' member.
7+
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(23,25): error TS1320: Type of 'await' operand must either be a valid promise or must not contain a callable 'then' member.
88

99

1010
==== tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts (7 errors) ====
@@ -36,13 +36,13 @@ tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration1
3636
async function fn12() { return obj; } // valid: Promise<{ then: string; }>
3737
async function fn13() { return thenable; } // error
3838
~~~~
39-
!!! error TS1058: Type used as operand to 'await' or the return type of an async function must either be a valid promise or must not contain a callable 'then' member.
39+
!!! error TS1058: The return type of an async function must either be a valid promise or must not contain a callable 'then' member.
4040
async function fn14() { await 1; } // valid: Promise<void>
4141
async function fn15() { await null; } // valid: Promise<void>
4242
async function fn16() { await undefined; } // valid: Promise<void>
4343
async function fn17() { await a; } // valid: Promise<void>
4444
async function fn18() { await obj; } // valid: Promise<void>
4545
async function fn19() { await thenable; } // error
4646
~~~~~~~~~~~~~~
47-
!!! error TS1058: Type used as operand to 'await' or the return type of an async function must either be a valid promise or must not contain a callable 'then' member.
47+
!!! error TS1320: Type of 'await' operand must either be a valid promise or must not contain a callable 'then' member.
4848

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.