Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12743,12 +12743,14 @@ namespace ts {

// Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual
// type checking functions).
function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): TypeParameter[] | undefined {
function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): readonly TypeParameter[] | undefined {
let result: TypeParameter[] | undefined;
for (const node of getEffectiveTypeParameterDeclarations(declaration)) {
result = appendIfUnique(result, getDeclaredTypeOfTypeParameter(node.symbol));
}
return result;
return result?.length ? result
: isFunctionDeclaration(declaration) ? getSignatureOfTypeTag(declaration)?.typeParameters
: undefined;
}

function symbolsToArray(symbols: SymbolTable): Symbol[] {
Expand Down
6 changes: 6 additions & 0 deletions src/compiler/utilitiesPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,12 @@ namespace ts {
/**
* Gets the effective type parameters. If the node was parsed in a
* JavaScript file, gets the type parameters from the `@template` tag from JSDoc.
*
* This does *not* return type parameters from a jsdoc reference to a generic type, eg
*
* type Id = <T>(x: T) => T
* /** @type {Id} /
* function id(x) { return x }
*/
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[] {
if (isJSDocSignature(node)) {
Expand Down
6 changes: 6 additions & 0 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4464,6 +4464,12 @@ declare namespace ts {
/**
* Gets the effective type parameters. If the node was parsed in a
* JavaScript file, gets the type parameters from the `@template` tag from JSDoc.
*
* This does *not* return type parameters from a jsdoc reference to a generic type, eg
*
* type Id = <T>(x: T) => T
* /** @type {Id} /
* function id(x) { return x }
*/
function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[];
function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined;
Expand Down
6 changes: 6 additions & 0 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4464,6 +4464,12 @@ declare namespace ts {
/**
* Gets the effective type parameters. If the node was parsed in a
* JavaScript file, gets the type parameters from the `@template` tag from JSDoc.
*
* This does *not* return type parameters from a jsdoc reference to a generic type, eg
*
* type Id = <T>(x: T) => T
* /** @type {Id} /
* function id(x) { return x }
*/
function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[];
function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined;
Expand Down
45 changes: 45 additions & 0 deletions tests/baselines/reference/typeTagOnFunctionReferencesGeneric.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//// [typeTagOnFunctionReferencesGeneric.js]
/**
* @typedef {<T>(m : T) => T} IFn
*/

/**@type {IFn}*/
export function inJs(l) {
return l;
}
inJs(1); // lints error. Why?

/**@type {IFn}*/
const inJsArrow = (j) => {
return j;
}
inJsArrow(2); // no error gets linted as expected


//// [typeTagOnFunctionReferencesGeneric.js]
"use strict";
/**
* @typedef {<T>(m : T) => T} IFn
*/
exports.__esModule = true;
exports.inJs = void 0;
/**@type {IFn}*/
function inJs(l) {
return l;
}
exports.inJs = inJs;
inJs(1); // lints error. Why?
/**@type {IFn}*/
var inJsArrow = function (j) {
return j;
};
inJsArrow(2); // no error gets linted as expected


//// [typeTagOnFunctionReferencesGeneric.d.ts]
/**
* @typedef {<T>(m : T) => T} IFn
*/
/**@type {IFn}*/
export function inJs<T>(l: T): T;
export type IFn = <T>(m: T) => T;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
=== tests/cases/conformance/salsa/typeTagOnFunctionReferencesGeneric.js ===
/**
* @typedef {<T>(m : T) => T} IFn
*/

/**@type {IFn}*/
export function inJs(l) {
>inJs : Symbol(inJs, Decl(typeTagOnFunctionReferencesGeneric.js, 0, 0))
>l : Symbol(l, Decl(typeTagOnFunctionReferencesGeneric.js, 5, 21))

return l;
>l : Symbol(l, Decl(typeTagOnFunctionReferencesGeneric.js, 5, 21))
}
inJs(1); // lints error. Why?
>inJs : Symbol(inJs, Decl(typeTagOnFunctionReferencesGeneric.js, 0, 0))

/**@type {IFn}*/
const inJsArrow = (j) => {
>inJsArrow : Symbol(inJsArrow, Decl(typeTagOnFunctionReferencesGeneric.js, 11, 5))
>j : Symbol(j, Decl(typeTagOnFunctionReferencesGeneric.js, 11, 19))

return j;
>j : Symbol(j, Decl(typeTagOnFunctionReferencesGeneric.js, 11, 19))
}
inJsArrow(2); // no error gets linted as expected
>inJsArrow : Symbol(inJsArrow, Decl(typeTagOnFunctionReferencesGeneric.js, 11, 5))

32 changes: 32 additions & 0 deletions tests/baselines/reference/typeTagOnFunctionReferencesGeneric.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
=== tests/cases/conformance/salsa/typeTagOnFunctionReferencesGeneric.js ===
/**
* @typedef {<T>(m : T) => T} IFn
*/

/**@type {IFn}*/
export function inJs(l) {
>inJs : <T>(l: T) => T
>l : T

return l;
>l : T
}
inJs(1); // lints error. Why?
>inJs(1) : 1
>inJs : <T>(l: T) => T
>1 : 1

/**@type {IFn}*/
const inJsArrow = (j) => {
>inJsArrow : IFn
>(j) => { return j;} : <T>(j: T) => T
>j : T

return j;
>j : T
}
inJsArrow(2); // no error gets linted as expected
>inJsArrow(2) : 2
>inJsArrow : IFn
>2 : 2

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// @checkJs: true
// @declaration: true
// @outDir: out/
// @filename: typeTagOnFunctionReferencesGeneric.js
/**
* @typedef {<T>(m : T) => T} IFn
*/

/**@type {IFn}*/
export function inJs(l) {
return l;
}
inJs(1); // lints error. Why?

/**@type {IFn}*/
const inJsArrow = (j) => {
return j;
}
inJsArrow(2); // no error gets linted as expected