Get [type] parameter types from @type tag (#26694)

* Get [type] parameter types from @type tag

Previously only the return type was used in cases like this:

```js
/** @type {<T>(param?: T) => T | undefined} */
function g(param) {
  return param;
}
```

Now the type parameters from the type tag are used, and the compiler
gets the type of the parameter by using the position in the signature of
the type tag.

Fixes #25618

* Fix split ifs according to PR comments
This commit is contained in:
Nathan Shively-Sanders
2018-08-27 16:52:35 -07:00
committed by GitHub
parent 4cf5774c5e
commit a2e4a282e7
5 changed files with 65 additions and 1 deletions
+6
View File
@@ -4699,6 +4699,12 @@ namespace ts {
return getReturnTypeOfSignature(getterSignature);
}
}
if (isInJavaScriptFile(declaration)) {
const typeTag = getJSDocType(func);
if (typeTag && isFunctionTypeNode(typeTag)) {
return getTypeAtPosition(getSignatureFromDeclaration(typeTag), func.parameters.indexOf(declaration));
}
}
// Use contextual parameter type if one is available
const type = declaration.symbol.escapedName === InternalSymbolName.This ? getContextualThisParameterType(func) : getContextuallyTypedParameterType(declaration);
if (type) {
+14 -1
View File
@@ -5116,7 +5116,20 @@ namespace ts {
Debug.assert(node.parent.kind === SyntaxKind.JSDocComment);
return flatMap(node.parent.tags, tag => isJSDocTemplateTag(tag) ? tag.typeParameters : undefined) as ReadonlyArray<TypeParameterDeclaration>;
}
return node.typeParameters || (isInJavaScriptFile(node) ? getJSDocTypeParameterDeclarations(node) : emptyArray);
if (node.typeParameters) {
return node.typeParameters;
}
if (isInJavaScriptFile(node)) {
const decls = getJSDocTypeParameterDeclarations(node);
if (decls.length) {
return decls;
}
const typeTag = getJSDocType(node);
if (typeTag && isFunctionTypeNode(typeTag) && typeTag.typeParameters) {
return typeTag.typeParameters;
}
}
return emptyArray;
}
export function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined {
@@ -0,0 +1,15 @@
=== tests/cases/conformance/jsdoc/bug25618.js ===
/** @type {<T>(param?: T) => T | undefined} */
function typed(param) {
>typed : Symbol(typed, Decl(bug25618.js, 0, 0))
>param : Symbol(param, Decl(bug25618.js, 1, 15))
return param;
>param : Symbol(param, Decl(bug25618.js, 1, 15))
}
var n = typed(1);
>n : Symbol(n, Decl(bug25618.js, 5, 3))
>typed : Symbol(typed, Decl(bug25618.js, 0, 0))
@@ -0,0 +1,17 @@
=== tests/cases/conformance/jsdoc/bug25618.js ===
/** @type {<T>(param?: T) => T | undefined} */
function typed(param) {
>typed : <T>(param: T | undefined) => T | undefined
>param : T | undefined
return param;
>param : T | undefined
}
var n = typed(1);
>n : number | undefined
>typed(1) : 1 | undefined
>typed : <T>(param: T | undefined) => T | undefined
>1 : 1
@@ -0,0 +1,13 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @strict: true
// @Filename: bug25618.js
/** @type {<T>(param?: T) => T | undefined} */
function typed(param) {
return param;
}
var n = typed(1);