getJSDocReturnType gets return type from @type tags (#25486)

* get return type from `@type` tags

Previously, getJSDocReturnType did not check the `@type` tag for a type
node that has a return type. Now it does.

* Improve doc comment of getJSDocReturnType

* More type predicates in type guards!

* Update API baselines with new documentation (?!)
This commit is contained in:
Nathan Shively-Sanders
2018-07-06 10:46:43 -07:00
committed by GitHub
parent c228924543
commit 6589e867fe
7 changed files with 154 additions and 47 deletions

View File

@@ -5007,14 +5007,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 {

View File

@@ -6772,10 +6772,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. */

View File

@@ -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. */

View File

@@ -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'.

View File

@@ -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))

View File

@@ -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

View File

@@ -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 }