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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 1 deletions

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

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 {

View File

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

View File

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

View File

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