diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 65335117cf204..ac378ef5fd8e0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8756,6 +8756,16 @@ namespace ts { function getContextualTypeForReturnExpression(node: Expression): Type { const func = getContainingFunction(node); + + if (isAsyncFunctionLike(func)) { + const contextualReturnType = getContextualReturnType(func); + if (contextualReturnType) { + return getPromisedType(contextualReturnType); + } + + return undefined; + } + if (func && !func.asteriskToken) { return getContextualReturnType(func); } diff --git a/tests/baselines/reference/asyncFunctionReturnType.js b/tests/baselines/reference/asyncFunctionReturnType.js new file mode 100644 index 0000000000000..12cb44fbcf069 --- /dev/null +++ b/tests/baselines/reference/asyncFunctionReturnType.js @@ -0,0 +1,33 @@ +//// [asyncFunctionReturnType.ts] +async function fAsync() { + // Without explicit type annotation, this is just an array. + return [1, true]; +} + +async function fAsyncExplicit(): Promise<[number, boolean]> { + // This is contextually typed as a tuple. + return [1, true]; +} + + +//// [asyncFunctionReturnType.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments)).next()); + }); +}; +function fAsync() { + return __awaiter(this, void 0, void 0, function* () { + // Without explicit type annotation, this is just an array. + return [1, true]; + }); +} +function fAsyncExplicit() { + return __awaiter(this, void 0, void 0, function* () { + // This is contextually typed as a tuple. + return [1, true]; + }); +} diff --git a/tests/baselines/reference/asyncFunctionReturnType.symbols b/tests/baselines/reference/asyncFunctionReturnType.symbols new file mode 100644 index 0000000000000..75e456b6a8b69 --- /dev/null +++ b/tests/baselines/reference/asyncFunctionReturnType.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/asyncFunctionReturnType.ts === +async function fAsync() { +>fAsync : Symbol(fAsync, Decl(asyncFunctionReturnType.ts, 0, 0)) + + // Without explicit type annotation, this is just an array. + return [1, true]; +} + +async function fAsyncExplicit(): Promise<[number, boolean]> { +>fAsyncExplicit : Symbol(fAsyncExplicit, Decl(asyncFunctionReturnType.ts, 3, 1)) +>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --)) + + // This is contextually typed as a tuple. + return [1, true]; +} + diff --git a/tests/baselines/reference/asyncFunctionReturnType.types b/tests/baselines/reference/asyncFunctionReturnType.types new file mode 100644 index 0000000000000..c6289ab012d5e --- /dev/null +++ b/tests/baselines/reference/asyncFunctionReturnType.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/asyncFunctionReturnType.ts === +async function fAsync() { +>fAsync : () => Promise<(number | boolean)[]> + + // Without explicit type annotation, this is just an array. + return [1, true]; +>[1, true] : (number | boolean)[] +>1 : number +>true : boolean +} + +async function fAsyncExplicit(): Promise<[number, boolean]> { +>fAsyncExplicit : () => Promise<[number, boolean]> +>Promise : Promise + + // This is contextually typed as a tuple. + return [1, true]; +>[1, true] : [number, boolean] +>1 : number +>true : boolean +} + diff --git a/tests/cases/compiler/asyncFunctionReturnType.ts b/tests/cases/compiler/asyncFunctionReturnType.ts new file mode 100644 index 0000000000000..a1bcde3807909 --- /dev/null +++ b/tests/cases/compiler/asyncFunctionReturnType.ts @@ -0,0 +1,10 @@ +// @target: ES6 +async function fAsync() { + // Without explicit type annotation, this is just an array. + return [1, true]; +} + +async function fAsyncExplicit(): Promise<[number, boolean]> { + // This is contextually typed as a tuple. + return [1, true]; +}