Git Product home page Git Product logo

Comments (1)

Andarist avatar Andarist commented on May 2, 2024 1

The problem is that @type can be a source of an effective return type node for an arrow function like this. I don't know all the rules but it's kinda like a mix of a contextual type and an explicit return type annotation. And an explicit return type annotation has to refer to Promise.

A quick experiment to ignore @type tags for this purpose here shows that it's not really a good idea:

git diff
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index d0a2843989..13407fdb86 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -39900,7 +39900,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
         function checkSignatureDeclarationDiagnostics() {
             checkCollisionWithArgumentsInGeneratedCode(node);
 
-            let returnTypeNode = getEffectiveReturnTypeNode(node);
+            let returnTypeNode = getEffectiveReturnTypeNode(node, /*ignoreTypeTag*/ true);
             let returnTypeErrorLocation = returnTypeNode;
 
             if (isInJSFile(node)) {
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 018eda7cb1..5ad67a9cd6 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -6657,10 +6657,10 @@ export function getTypeAnnotationNode(node: Node): TypeNode | undefined {
  *
  * @internal
  */
-export function getEffectiveReturnTypeNode(node: SignatureDeclaration | JSDocSignature): TypeNode | undefined {
+export function getEffectiveReturnTypeNode(node: SignatureDeclaration | JSDocSignature, ignoreTypeTag = false): TypeNode | undefined {
     return isJSDocSignature(node) ?
         node.type && node.type.typeExpression && node.type.typeExpression.type :
-        node.type || (isInJSFile(node) ? getJSDocReturnType(node) : undefined);
+        node.type || (isInJSFile(node) ? getJSDocReturnType(node, ignoreTypeTag) : undefined);
 }
 
 /** @internal */
diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts
index 60e19b0e47..b8370acca9 100644
--- a/src/compiler/utilitiesPublic.ts
+++ b/src/compiler/utilitiesPublic.ts
@@ -1182,11 +1182,14 @@ export function getJSDocType(node: Node): TypeNode | undefined {
  * @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function
  * gets the type from inside the braces, after the fat arrow, etc.
  */
-export function getJSDocReturnType(node: Node): TypeNode | undefined {
+export function getJSDocReturnType(node: Node, ignoreTypeTag = false): TypeNode | undefined {
     const returnTag = getJSDocReturnTag(node);
     if (returnTag && returnTag.typeExpression) {
         return returnTag.typeExpression.type;
     }
+    if (ignoreTypeTag) {
+        return;
+    }
     const typeTag = getJSDocTypeTag(node);
     if (typeTag && typeTag.typeExpression) {
         const type = typeTag.typeExpression.type;
diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts
index ad1b05ed05..aa5623451e 100644
--- a/tests/baselines/reference/api/typescript.d.ts
+++ b/tests/baselines/reference/api/typescript.d.ts
@@ -8577,7 +8577,7 @@ declare namespace ts {
      * @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function
      * gets the type from inside the braces, after the fat arrow, etc.
      */
-    function getJSDocReturnType(node: Node): TypeNode | undefined;
+    function getJSDocReturnType(node: Node, ignoreTypeTag?: boolean): TypeNode | undefined;
     /** Get all JSDoc tags related to a node, including those on parent nodes. */
     function getJSDocTags(node: Node): readonly JSDocTag[];
     /** Gets all JSDoc tags that match a specified predicate */
diff --git a/tests/baselines/reference/asyncArrowFunction_allowJs.errors.txt b/tests/baselines/reference/asyncArrowFunction_allowJs.errors.txt
index 417262fef3..36b0ddea7b 100644
--- a/tests/baselines/reference/asyncArrowFunction_allowJs.errors.txt
+++ b/tests/baselines/reference/asyncArrowFunction_allowJs.errors.txt
@@ -1,13 +1,11 @@
 file.js(3,17): error TS2322: Type 'number' is not assignable to type 'string'.
-file.js(6,24): error TS1064: The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<string>'?
 file.js(7,23): error TS2322: Type 'number' is not assignable to type 'string'.
-file.js(10,24): error TS1064: The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<string>'?
 file.js(12,2): error TS2322: Type 'number' is not assignable to type 'string'.
-file.js(19,3): error TS2345: Argument of type '() => Promise<number>' is not assignable to parameter of type '() => string'.
+file.js(24,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'.
 
 
-==== file.js (6 errors) ====
+==== file.js (4 errors) ====
     // Error (good)
     /** @type {function(): string} */
     const a = () => 0
@@ -16,22 +14,23 @@ file.js(19,3): error TS2345: Argument of type '() => Promise<number>' is not ass
     
     // Error (good)
     /** @type {function(): string} */
-                           ~~~~~~
-!!! error TS1064: The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<string>'?
     const b = async () => 0
                           ~
 !!! error TS2322: Type 'number' is not assignable to type 'string'.
     
     // No error (bad)
     /** @type {function(): string} */
-                           ~~~~~~
-!!! error TS1064: The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<string>'?
     const c = async () => {
     	return 0
     	~~~~~~
 !!! error TS2322: Type 'number' is not assignable to type 'string'.
     }
     
+    /** @type {function(): string} */
+    const d = async () => {
+    	return ""
+    }
+    
     /** @type {function(function(): string): void} */
     const f = (p) => {}
     
diff --git a/tests/baselines/reference/asyncArrowFunction_allowJs.symbols b/tests/baselines/reference/asyncArrowFunction_allowJs.symbols
index 6cb66a2b9e..8ee40f15df 100644
--- a/tests/baselines/reference/asyncArrowFunction_allowJs.symbols
+++ b/tests/baselines/reference/asyncArrowFunction_allowJs.symbols
@@ -19,14 +19,21 @@ const c = async () => {
 	return 0
 }
 
+/** @type {function(): string} */
+const d = async () => {
+>d : Symbol(d, Decl(file.js, 15, 5))
+
+	return ""
+}
+
 /** @type {function(function(): string): void} */
 const f = (p) => {}
->f : Symbol(f, Decl(file.js, 15, 5))
->p : Symbol(p, Decl(file.js, 15, 11))
+>f : Symbol(f, Decl(file.js, 20, 5))
+>p : Symbol(p, Decl(file.js, 20, 11))
 
 // Error (good)
 f(async () => {
->f : Symbol(f, Decl(file.js, 15, 5))
+>f : Symbol(f, Decl(file.js, 20, 5))
 
 	return 0
 })
diff --git a/tests/baselines/reference/asyncArrowFunction_allowJs.types b/tests/baselines/reference/asyncArrowFunction_allowJs.types
index ecf9f7d9cc..068136f341 100644
--- a/tests/baselines/reference/asyncArrowFunction_allowJs.types
+++ b/tests/baselines/reference/asyncArrowFunction_allowJs.types
@@ -34,6 +34,18 @@ const c = async () => {
 >  : ^
 }
 
+/** @type {function(): string} */
+const d = async () => {
+>d : () => string
+>  : ^^^^^^^^^^^^
+>async () => {	return ""} : () => string
+>                         : ^^^^^^^^^^^^
+
+	return ""
+>"" : ""
+>   : ^^
+}
+
 /** @type {function(function(): string): void} */
 const f = (p) => {}
 >f : (arg0: () => string) => void
diff --git a/tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction_allowJs.ts b/tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction_allowJs.ts
index 9c21ae8557..7e490966d1 100644
--- a/tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction_allowJs.ts
+++ b/tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction_allowJs.ts
@@ -18,6 +18,11 @@ const c = async () => {
 	return 0
 }
 
+/** @type {function(): string} */
+const d = async () => {
+	return ""
+}
+
 /** @type {function(function(): string): void} */
 const f = (p) => {}

Some of the errors in asyncArrowFunction_allowJs became confusing (they don't mention Promise at all now). There is also no error reported for the d function that I added there which is super bad.

from typescript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.