mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Fix async function block return expr error in js (#37845)
This commit is contained in:
@@ -27244,7 +27244,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const functionFlags = getFunctionFlags(func);
|
||||
const type = returnType && getReturnOrPromisedType(returnType, functionFlags);
|
||||
const type = returnType && unwrapReturnType(returnType, functionFlags);
|
||||
|
||||
// Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
|
||||
if (type && maybeTypeOfKind(type, TypeFlags.Any | TypeFlags.Void)) {
|
||||
@@ -27364,14 +27364,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getReturnOrPromisedType(type: Type | undefined, functionFlags: FunctionFlags) {
|
||||
const isGenerator = !!(functionFlags & FunctionFlags.Generator);
|
||||
const isAsync = !!(functionFlags & FunctionFlags.Async);
|
||||
return type && isGenerator ? getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, type, isAsync) || errorType :
|
||||
type && isAsync ? getAwaitedType(type) || errorType :
|
||||
type;
|
||||
}
|
||||
|
||||
function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) {
|
||||
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
|
||||
|
||||
@@ -27399,7 +27391,7 @@ namespace ts {
|
||||
// check assignability of the awaited type of the expression body against the promised type of
|
||||
// its return type annotation.
|
||||
const exprType = checkExpression(node.body);
|
||||
const returnOrPromisedType = getReturnOrPromisedType(returnType, functionFlags);
|
||||
const returnOrPromisedType = returnType && unwrapReturnType(returnType, functionFlags);
|
||||
if (returnOrPromisedType) {
|
||||
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { // Async function
|
||||
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);
|
||||
@@ -32687,8 +32679,8 @@ namespace ts {
|
||||
function unwrapReturnType(returnType: Type, functionFlags: FunctionFlags) {
|
||||
const isGenerator = !!(functionFlags & FunctionFlags.Generator);
|
||||
const isAsync = !!(functionFlags & FunctionFlags.Async);
|
||||
return isGenerator ? getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, isAsync) || errorType :
|
||||
isAsync ? getPromisedTypeOfPromise(returnType) || errorType :
|
||||
return isGenerator ? getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, isAsync) ?? errorType :
|
||||
isAsync ? getAwaitedType(returnType) ?? errorType :
|
||||
returnType;
|
||||
}
|
||||
|
||||
@@ -32725,7 +32717,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (getReturnTypeFromAnnotation(func)) {
|
||||
const unwrappedReturnType = unwrapReturnType(returnType, functionFlags);
|
||||
const unwrappedReturnType = unwrapReturnType(returnType, functionFlags) ?? returnType;
|
||||
const unwrappedExprType = functionFlags & FunctionFlags.Async
|
||||
? 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)
|
||||
: exprType;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
tests/cases/conformance/async/es2017/asyncArrowFunction/file.js(3,17): error TS2322: Type '0' is not assignable to type 'string'.
|
||||
tests/cases/conformance/async/es2017/asyncArrowFunction/file.js(7,23): error TS2322: Type '0' is not assignable to type 'string'.
|
||||
tests/cases/conformance/async/es2017/asyncArrowFunction/file.js(12,2): error TS2322: Type '0' is not assignable to type 'string'.
|
||||
tests/cases/conformance/async/es2017/asyncArrowFunction/file.js(19,3): error TS2345: Argument of type '() => Promise<number>' is not assignable to parameter of type '() => string'.
|
||||
Type 'Promise<number>' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/async/es2017/asyncArrowFunction/file.js (4 errors) ====
|
||||
// Error (good)
|
||||
/** @type {function(): string} */
|
||||
const a = () => 0
|
||||
~
|
||||
!!! error TS2322: Type '0' is not assignable to type 'string'.
|
||||
|
||||
// Error (good)
|
||||
/** @type {function(): string} */
|
||||
const b = async () => 0
|
||||
~
|
||||
!!! error TS2322: Type '0' is not assignable to type 'string'.
|
||||
|
||||
// No error (bad)
|
||||
/** @type {function(): string} */
|
||||
const c = async () => {
|
||||
return 0
|
||||
~~~~~~~~
|
||||
!!! error TS2322: Type '0' is not assignable to type 'string'.
|
||||
}
|
||||
|
||||
/** @type {function(function(): string): void} */
|
||||
const f = (p) => {}
|
||||
|
||||
// Error (good)
|
||||
f(async () => {
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '() => Promise<number>' is not assignable to parameter of type '() => string'.
|
||||
!!! error TS2345: Type 'Promise<number>' is not assignable to type 'string'.
|
||||
return 0
|
||||
})
|
||||
30
tests/baselines/reference/asyncArrowFunction_allowJs.symbols
Normal file
30
tests/baselines/reference/asyncArrowFunction_allowJs.symbols
Normal file
@@ -0,0 +1,30 @@
|
||||
=== tests/cases/conformance/async/es2017/asyncArrowFunction/file.js ===
|
||||
// Error (good)
|
||||
/** @type {function(): string} */
|
||||
const a = () => 0
|
||||
>a : Symbol(a, Decl(file.js, 2, 5))
|
||||
|
||||
// Error (good)
|
||||
/** @type {function(): string} */
|
||||
const b = async () => 0
|
||||
>b : Symbol(b, Decl(file.js, 6, 5))
|
||||
|
||||
// No error (bad)
|
||||
/** @type {function(): string} */
|
||||
const c = async () => {
|
||||
>c : Symbol(c, Decl(file.js, 10, 5))
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
/** @type {function(function(): string): void} */
|
||||
const f = (p) => {}
|
||||
>f : Symbol(f, Decl(file.js, 15, 5))
|
||||
>p : Symbol(p, Decl(file.js, 15, 11))
|
||||
|
||||
// Error (good)
|
||||
f(async () => {
|
||||
>f : Symbol(f, Decl(file.js, 15, 5))
|
||||
|
||||
return 0
|
||||
})
|
||||
41
tests/baselines/reference/asyncArrowFunction_allowJs.types
Normal file
41
tests/baselines/reference/asyncArrowFunction_allowJs.types
Normal file
@@ -0,0 +1,41 @@
|
||||
=== tests/cases/conformance/async/es2017/asyncArrowFunction/file.js ===
|
||||
// Error (good)
|
||||
/** @type {function(): string} */
|
||||
const a = () => 0
|
||||
>a : () => string
|
||||
>() => 0 : () => string
|
||||
>0 : 0
|
||||
|
||||
// Error (good)
|
||||
/** @type {function(): string} */
|
||||
const b = async () => 0
|
||||
>b : () => string
|
||||
>async () => 0 : () => string
|
||||
>0 : 0
|
||||
|
||||
// No error (bad)
|
||||
/** @type {function(): string} */
|
||||
const c = async () => {
|
||||
>c : () => string
|
||||
>async () => { return 0} : () => string
|
||||
|
||||
return 0
|
||||
>0 : 0
|
||||
}
|
||||
|
||||
/** @type {function(function(): string): void} */
|
||||
const f = (p) => {}
|
||||
>f : (arg0: () => string) => void
|
||||
>(p) => {} : (p: () => string) => void
|
||||
>p : () => string
|
||||
|
||||
// Error (good)
|
||||
f(async () => {
|
||||
>f(async () => { return 0}) : void
|
||||
>f : (arg0: () => string) => void
|
||||
>async () => { return 0} : () => Promise<number>
|
||||
|
||||
return 0
|
||||
>0 : 0
|
||||
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noEmit: true
|
||||
// @target: es2017
|
||||
// @filename: file.js
|
||||
|
||||
// Error (good)
|
||||
/** @type {function(): string} */
|
||||
const a = () => 0
|
||||
|
||||
// Error (good)
|
||||
/** @type {function(): string} */
|
||||
const b = async () => 0
|
||||
|
||||
// No error (bad)
|
||||
/** @type {function(): string} */
|
||||
const c = async () => {
|
||||
return 0
|
||||
}
|
||||
|
||||
/** @type {function(function(): string): void} */
|
||||
const f = (p) => {}
|
||||
|
||||
// Error (good)
|
||||
f(async () => {
|
||||
return 0
|
||||
})
|
||||
Reference in New Issue
Block a user