diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c5fa7d155d519..d98445c4316b4 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -5022,14 +5022,27 @@ namespace ts { } /** - * Gets the return type node for the node if provided via JSDoc's return tag. + * Gets the return type node for the node if provided via JSDoc return tag or type tag. * * @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function - * gets the type from inside the braces. + * gets the type from inside the braces, after the fat arrow, etc. */ export function getJSDocReturnType(node: Node): TypeNode | undefined { const returnTag = getJSDocReturnTag(node); - return returnTag && returnTag.typeExpression && returnTag.typeExpression.type; + if (returnTag && returnTag.typeExpression) { + return returnTag.typeExpression.type; + } + const typeTag = getJSDocTypeTag(node); + if (typeTag && typeTag.typeExpression) { + const type = typeTag.typeExpression.type; + if (isTypeLiteralNode(type)) { + const sig = find(type.members, isCallSignatureDeclaration); + return sig && sig.type; + } + if (isFunctionTypeNode(type)) { + return type.type; + } + } } /** Get all JSDoc tags related to a node, including those on parent nodes. */ @@ -6572,45 +6585,6 @@ namespace ts { return !!(node as HasType).type; } - /* True if the node could have a type node a `.type` */ - /* @internal */ - export function couldHaveType(node: Node): node is HasType { - switch (node.kind) { - case SyntaxKind.Parameter: - case SyntaxKind.PropertySignature: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.Constructor: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.CallSignature: - case SyntaxKind.ConstructSignature: - case SyntaxKind.IndexSignature: - case SyntaxKind.TypePredicate: - case SyntaxKind.FunctionType: - case SyntaxKind.ConstructorType: - case SyntaxKind.ParenthesizedType: - case SyntaxKind.TypeOperator: - case SyntaxKind.MappedType: - case SyntaxKind.TypeAssertionExpression: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.AsExpression: - case SyntaxKind.VariableDeclaration: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.TypeAliasDeclaration: - case SyntaxKind.JSDocTypeExpression: - case SyntaxKind.JSDocNullableType: - case SyntaxKind.JSDocNonNullableType: - case SyntaxKind.JSDocOptionalType: - case SyntaxKind.JSDocFunctionType: - case SyntaxKind.JSDocVariadicType: - return true; - } - return false; - } - /** True if has initializer node attached to it. */ /* @internal */ export function hasInitializer(node: Node): node is HasInitializer { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 82b7e0c3ef833..06650d20c71b0 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -6777,10 +6777,10 @@ declare namespace ts { */ function getJSDocType(node: Node): TypeNode | undefined; /** - * Gets the return type node for the node if provided via JSDoc's return tag. + * Gets the return type node for the node if provided via JSDoc return tag or type tag. * * @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function - * gets the type from inside the braces. + * gets the type from inside the braces, after the fat arrow, etc. */ function getJSDocReturnType(node: Node): TypeNode | undefined; /** Get all JSDoc tags related to a node, including those on parent nodes. */ @@ -7072,7 +7072,6 @@ declare namespace ts { function hasJSDocNodes(node: Node): node is HasJSDoc; /** True if has type node attached to it. */ function hasType(node: Node): node is HasType; - function couldHaveType(node: Node): node is HasType; /** True if has initializer node attached to it. */ function hasInitializer(node: Node): node is HasInitializer; /** True if has initializer node attached to it. */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index f20c70e009586..e036deb703b1f 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3227,10 +3227,10 @@ declare namespace ts { */ function getJSDocType(node: Node): TypeNode | undefined; /** - * Gets the return type node for the node if provided via JSDoc's return tag. + * Gets the return type node for the node if provided via JSDoc return tag or type tag. * * @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function - * gets the type from inside the braces. + * gets the type from inside the braces, after the fat arrow, etc. */ function getJSDocReturnType(node: Node): TypeNode | undefined; /** Get all JSDoc tags related to a node, including those on parent nodes. */ diff --git a/tests/baselines/reference/checkJsdocTypeTag5.errors.txt b/tests/baselines/reference/checkJsdocTypeTag5.errors.txt new file mode 100644 index 0000000000000..98510f63815be --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypeTag5.errors.txt @@ -0,0 +1,36 @@ +tests/cases/conformance/jsdoc/test.js(3,17): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/test.js(5,14): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/test.js(7,24): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/test.js(10,17): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/test.js(12,14): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/test.js(14,24): error TS2322: Type 'number' is not assignable to type 'string'. + + +==== tests/cases/conformance/jsdoc/test.js (6 errors) ==== + // all 6 should error on return statement/expression + /** @type {(x: number) => string} */ + function h(x) { return x } + ~~~~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + /** @type {(x: number) => string} */ + var f = x => x + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + /** @type {(x: number) => string} */ + var g = function (x) { return x } + ~~~~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + + /** @type {{ (x: number): string }} */ + function i(x) { return x } + ~~~~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + /** @type {{ (x: number): string }} */ + var j = x => x + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + /** @type {{ (x: number): string }} */ + var k = function (x) { return x } + ~~~~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/checkJsdocTypeTag5.symbols b/tests/baselines/reference/checkJsdocTypeTag5.symbols new file mode 100644 index 0000000000000..839fba179ac1f --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypeTag5.symbols @@ -0,0 +1,38 @@ +=== tests/cases/conformance/jsdoc/test.js === +// all 6 should error on return statement/expression +/** @type {(x: number) => string} */ +function h(x) { return x } +>h : Symbol(h, Decl(test.js, 0, 0)) +>x : Symbol(x, Decl(test.js, 2, 11)) +>x : Symbol(x, Decl(test.js, 2, 11)) + +/** @type {(x: number) => string} */ +var f = x => x +>f : Symbol(f, Decl(test.js, 4, 3)) +>x : Symbol(x, Decl(test.js, 4, 7)) +>x : Symbol(x, Decl(test.js, 4, 7)) + +/** @type {(x: number) => string} */ +var g = function (x) { return x } +>g : Symbol(g, Decl(test.js, 6, 3)) +>x : Symbol(x, Decl(test.js, 6, 18)) +>x : Symbol(x, Decl(test.js, 6, 18)) + +/** @type {{ (x: number): string }} */ +function i(x) { return x } +>i : Symbol(i, Decl(test.js, 6, 33)) +>x : Symbol(x, Decl(test.js, 9, 11)) +>x : Symbol(x, Decl(test.js, 9, 11)) + +/** @type {{ (x: number): string }} */ +var j = x => x +>j : Symbol(j, Decl(test.js, 11, 3)) +>x : Symbol(x, Decl(test.js, 11, 7)) +>x : Symbol(x, Decl(test.js, 11, 7)) + +/** @type {{ (x: number): string }} */ +var k = function (x) { return x } +>k : Symbol(k, Decl(test.js, 13, 3)) +>x : Symbol(x, Decl(test.js, 13, 18)) +>x : Symbol(x, Decl(test.js, 13, 18)) + diff --git a/tests/baselines/reference/checkJsdocTypeTag5.types b/tests/baselines/reference/checkJsdocTypeTag5.types new file mode 100644 index 0000000000000..1038fe0ff3c74 --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypeTag5.types @@ -0,0 +1,42 @@ +=== tests/cases/conformance/jsdoc/test.js === +// all 6 should error on return statement/expression +/** @type {(x: number) => string} */ +function h(x) { return x } +>h : (x: number) => string +>x : number +>x : number + +/** @type {(x: number) => string} */ +var f = x => x +>f : (x: number) => string +>x => x : (x: number) => string +>x : number +>x : number + +/** @type {(x: number) => string} */ +var g = function (x) { return x } +>g : (x: number) => string +>function (x) { return x } : (x: number) => string +>x : number +>x : number + +/** @type {{ (x: number): string }} */ +function i(x) { return x } +>i : (x: number) => string +>x : number +>x : number + +/** @type {{ (x: number): string }} */ +var j = x => x +>j : (x: number) => string +>x => x : (x: number) => string +>x : number +>x : number + +/** @type {{ (x: number): string }} */ +var k = function (x) { return x } +>k : (x: number) => string +>function (x) { return x } : (x: number) => string +>x : number +>x : number + diff --git a/tests/cases/conformance/jsdoc/checkJsdocTypeTag5.ts b/tests/cases/conformance/jsdoc/checkJsdocTypeTag5.ts new file mode 100644 index 0000000000000..f56b99b9e99e9 --- /dev/null +++ b/tests/cases/conformance/jsdoc/checkJsdocTypeTag5.ts @@ -0,0 +1,18 @@ +// @checkJs: true +// @allowJs: true +// @noEmit: true +// @Filename: test.js +// all 6 should error on return statement/expression +/** @type {(x: number) => string} */ +function h(x) { return x } +/** @type {(x: number) => string} */ +var f = x => x +/** @type {(x: number) => string} */ +var g = function (x) { return x } + +/** @type {{ (x: number): string }} */ +function i(x) { return x } +/** @type {{ (x: number): string }} */ +var j = x => x +/** @type {{ (x: number): string }} */ +var k = function (x) { return x }