Look for outer type parameters on VariableStatements (#37819)

This only applies in JS, where `@template` tags can apply to
initialisers of variable declarations:

```js
/**
 * @template T
 * @returns {(b: T) => T}
 */
const seq = a => b => b
```

Fixes #36201
This commit is contained in:
Nathan Shively-Sanders
2020-04-07 08:04:33 -07:00
committed by GitHub
parent a2609b1f1b
commit 7ca6334dbd
5 changed files with 100 additions and 0 deletions
+4
View File
@@ -8238,6 +8238,7 @@ namespace ts {
return undefined;
}
switch (node.kind) {
case SyntaxKind.VariableStatement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
case SyntaxKind.InterfaceDeclaration:
@@ -8265,6 +8266,9 @@ namespace ts {
else if (node.kind === SyntaxKind.ConditionalType) {
return concatenate(outerTypeParameters, getInferTypeParameters(<ConditionalTypeNode>node));
}
else if (node.kind === SyntaxKind.VariableStatement && !isInJSFile(node)) {
break;
}
const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(<DeclarationWithTypeParameters>node));
const thisType = includeThisTypes &&
(node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) &&
@@ -0,0 +1,23 @@
//// [instantiateTemplateTagTypeParameterOnVariableStatement.js]
/**
* @template T
* @param {T} a
* @returns {(b: T) => T}
*/
const seq = a => b => b;
const text1 = "hello";
const text2 = "world";
/** @type {string} */
var text3 = seq(text1)(text2);
//// [instantiateTemplateTagTypeParameterOnVariableStatement.d.ts]
declare function seq<T>(a: T): (b: T) => T;
declare const text1: "hello";
declare const text2: "world";
/** @type {string} */
declare var text3: string;
@@ -0,0 +1,25 @@
=== tests/cases/conformance/jsdoc/instantiateTemplateTagTypeParameterOnVariableStatement.js ===
/**
* @template T
* @param {T} a
* @returns {(b: T) => T}
*/
const seq = a => b => b;
>seq : Symbol(seq, Decl(instantiateTemplateTagTypeParameterOnVariableStatement.js, 5, 5))
>a : Symbol(a, Decl(instantiateTemplateTagTypeParameterOnVariableStatement.js, 5, 11))
>b : Symbol(b, Decl(instantiateTemplateTagTypeParameterOnVariableStatement.js, 5, 16))
>b : Symbol(b, Decl(instantiateTemplateTagTypeParameterOnVariableStatement.js, 5, 16))
const text1 = "hello";
>text1 : Symbol(text1, Decl(instantiateTemplateTagTypeParameterOnVariableStatement.js, 7, 5))
const text2 = "world";
>text2 : Symbol(text2, Decl(instantiateTemplateTagTypeParameterOnVariableStatement.js, 8, 5))
/** @type {string} */
var text3 = seq(text1)(text2);
>text3 : Symbol(text3, Decl(instantiateTemplateTagTypeParameterOnVariableStatement.js, 11, 3))
>seq : Symbol(seq, Decl(instantiateTemplateTagTypeParameterOnVariableStatement.js, 5, 5))
>text1 : Symbol(text1, Decl(instantiateTemplateTagTypeParameterOnVariableStatement.js, 7, 5))
>text2 : Symbol(text2, Decl(instantiateTemplateTagTypeParameterOnVariableStatement.js, 8, 5))
@@ -0,0 +1,31 @@
=== tests/cases/conformance/jsdoc/instantiateTemplateTagTypeParameterOnVariableStatement.js ===
/**
* @template T
* @param {T} a
* @returns {(b: T) => T}
*/
const seq = a => b => b;
>seq : <T>(a: T) => (b: T) => T
>a => b => b : <T>(a: T) => (b: T) => T
>a : T
>b => b : (b: T) => T
>b : T
>b : T
const text1 = "hello";
>text1 : "hello"
>"hello" : "hello"
const text2 = "world";
>text2 : "world"
>"world" : "world"
/** @type {string} */
var text3 = seq(text1)(text2);
>text3 : string
>seq(text1)(text2) : string
>seq(text1) : (b: string) => string
>seq : <T>(a: T) => (b: T) => T
>text1 : "hello"
>text2 : "world"
@@ -0,0 +1,17 @@
// @checkJs: true
// @allowJs: true
// @declaration: true
// @emitDeclarationOnly: true
// @filename: instantiateTemplateTagTypeParameterOnVariableStatement.js
/**
* @template T
* @param {T} a
* @returns {(b: T) => T}
*/
const seq = a => b => b;
const text1 = "hello";
const text2 = "world";
/** @type {string} */
var text3 = seq(text1)(text2);