@@ -7566,12 +7566,21 @@ namespace ts {
7566
7566
const setter = getDeclarationOfKind<AccessorDeclaration>(getSymbolOfNode(declaration), SyntaxKind.SetAccessor);
7567
7567
return getAnnotatedAccessorType(setter);
7568
7568
}
7569
-
7569
+ const typeFromTag = getReturnTypeOfTypeTag(declaration);
7570
+ if (typeFromTag) {
7571
+ return typeFromTag;
7572
+ }
7570
7573
if (nodeIsMissing((<FunctionLikeDeclaration>declaration).body)) {
7571
7574
return anyType;
7572
7575
}
7573
7576
}
7574
7577
7578
+ function getReturnTypeOfTypeTag(node: SignatureDeclaration | JSDocSignature) {
7579
+ const typeTag = isInJavaScriptFile(node) ? getJSDocTypeTag(node) : undefined;
7580
+ const signatures = typeTag && typeTag.typeExpression && getSignaturesOfType(getTypeFromTypeNode(typeTag.typeExpression), SignatureKind.Call);
7581
+ return signatures && signatures.length === 1 ? getReturnTypeOfSignature(signatures[0]) : undefined;
7582
+ }
7583
+
7575
7584
function containsArgumentsReference(declaration: SignatureDeclaration): boolean {
7576
7585
const links = getNodeLinks(declaration);
7577
7586
if (links.containsArgumentsReference === undefined) {
@@ -20539,23 +20548,28 @@ namespace ts {
20539
20548
return type;
20540
20549
}
20541
20550
20551
+ function getReturnOrPromisedType(node: FunctionLikeDeclaration | MethodSignature, functionFlags: FunctionFlags) {
20552
+ const returnTypeNode = getEffectiveReturnTypeNode(node);
20553
+ return returnTypeNode &&
20554
+ ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async ?
20555
+ checkAsyncFunctionReturnType(node, returnTypeNode) : // Async function
20556
+ getTypeFromTypeNode(returnTypeNode)) || // AsyncGenerator function, Generator function, or normal function
20557
+ getReturnTypeOfTypeTag(node); // type from JSDoc @type tag
20558
+ }
20559
+
20542
20560
function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) {
20543
20561
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
20544
20562
20545
20563
const functionFlags = getFunctionFlags(node);
20546
- const returnTypeNode = getEffectiveReturnTypeNode(node);
20547
- const returnOrPromisedType = returnTypeNode &&
20548
- ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async ?
20549
- checkAsyncFunctionReturnType(node) : // Async function
20550
- getTypeFromTypeNode(returnTypeNode)); // AsyncGenerator function, Generator function, or normal function
20564
+ const returnOrPromisedType = getReturnOrPromisedType(node, functionFlags);
20551
20565
20552
20566
if ((functionFlags & FunctionFlags.Generator) === 0) { // Async function or normal function
20553
20567
// return is not necessary in the body of generators
20554
20568
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
20555
20569
}
20556
20570
20557
20571
if (node.body) {
20558
- if (!returnTypeNode ) {
20572
+ if (!getEffectiveReturnTypeNode(node) ) {
20559
20573
// There are some checks that are only performed in getReturnTypeFromBody, that may produce errors
20560
20574
// we need. An example is the noImplicitAny errors resulting from widening the return expression
20561
20575
// of a function. Because checking of function expression bodies is deferred, there was never an
@@ -22007,7 +22021,7 @@ namespace ts {
22007
22021
}
22008
22022
}
22009
22023
else if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) {
22010
- checkAsyncFunctionReturnType(<FunctionLikeDeclaration>node);
22024
+ checkAsyncFunctionReturnType(<FunctionLikeDeclaration>node, returnTypeNode );
22011
22025
}
22012
22026
}
22013
22027
if (node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.JSDocFunctionType) {
@@ -23067,7 +23081,7 @@ namespace ts {
23067
23081
*
23068
23082
* @param node The signature to check
23069
23083
*/
23070
- function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration | MethodSignature): Type {
23084
+ function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration | MethodSignature, returnTypeNode: TypeNode ): Type {
23071
23085
// As part of our emit for an async function, we will need to emit the entity name of
23072
23086
// the return type annotation as an expression. To meet the necessary runtime semantics
23073
23087
// for __awaiter, we must also check that the type of the declaration (e.g. the static
@@ -23092,7 +23106,6 @@ namespace ts {
23092
23106
// then<U>(...): Promise<U>;
23093
23107
// }
23094
23108
//
23095
- const returnTypeNode = getEffectiveReturnTypeNode(node)!; // TODO: GH#18217
23096
23109
const returnType = getTypeFromTypeNode(returnTypeNode);
23097
23110
23098
23111
if (languageVersion >= ScriptTarget.ES2015) {
@@ -23502,15 +23515,12 @@ namespace ts {
23502
23515
const body = node.kind === SyntaxKind.MethodSignature ? undefined : node.body;
23503
23516
checkSourceElement(body);
23504
23517
23505
- const returnTypeNode = getEffectiveReturnTypeNode(node);
23506
23518
if ((functionFlags & FunctionFlags.Generator) === 0) { // Async function or normal function
23507
- const returnOrPromisedType = returnTypeNode && (functionFlags & FunctionFlags.Async
23508
- ? checkAsyncFunctionReturnType(node) // Async function
23509
- : getTypeFromTypeNode(returnTypeNode)); // normal function
23519
+ const returnOrPromisedType = getReturnOrPromisedType(node, functionFlags);
23510
23520
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
23511
23521
}
23512
23522
23513
- if (produceDiagnostics && !returnTypeNode ) {
23523
+ if (produceDiagnostics && !getEffectiveReturnTypeNode(node) ) {
23514
23524
// Report an implicit any error if there is no body, no explicit return type, and node is not a private method
23515
23525
// in an ambient context
23516
23526
if (noImplicitAny && nodeIsMissing(body) && !isPrivateWithinAmbient(node)) {
@@ -23523,6 +23533,13 @@ namespace ts {
23523
23533
// yielded values. The only way to trigger these errors is to try checking its return type.
23524
23534
getReturnTypeOfSignature(getSignatureFromDeclaration(node));
23525
23535
}
23536
+ // A js function declaration can have a @type tag instead of a return type node, but that type must have a call signature
23537
+ if (isInJavaScriptFile(node)) {
23538
+ const typeTag = getJSDocTypeTag(node);
23539
+ if (typeTag && typeTag.typeExpression && !getSignaturesOfType(getTypeFromTypeNode(typeTag.typeExpression), SignatureKind.Call).length) {
23540
+ error(typeTag, Diagnostics.The_type_of_a_function_declaration_must_be_callable);
23541
+ }
23542
+ }
23526
23543
}
23527
23544
}
23528
23545
@@ -24785,7 +24802,7 @@ namespace ts {
24785
24802
error(node, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
24786
24803
}
24787
24804
}
24788
- else if (getEffectiveReturnTypeNode(func) || isGetAccessorWithAnnotatedSetAccessor(func)) {
24805
+ else if (getEffectiveReturnTypeNode(func) || isGetAccessorWithAnnotatedSetAccessor(func) || getReturnTypeOfTypeTag(func) ) {
24789
24806
if (functionFlags & FunctionFlags.Async) { // Async function
24790
24807
const promisedType = getPromisedTypeOfPromise(returnType);
24791
24808
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);
0 commit comments