mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-10 15:25:54 -06:00
Fix @param type parameter lookup (#39532)
Previously, getObjectTypeInstantiation had special-case code to look up type parameters for `@param` as if they were in the parameter location. This should occur in the main lookup loop of `getOuterTypeParameters`, however. The current code only runs once, which is not sufficient, and it also jumps to the parameter for any type contained in a `@param`, which skips type parameters that occur in the tag itself.
This commit is contained in:
parent
b397d1fd4a
commit
3b107fec3b
@ -8758,6 +8758,12 @@ namespace ts {
|
||||
(node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) &&
|
||||
getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node as ClassLikeDeclaration | InterfaceDeclaration)).thisType;
|
||||
return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters;
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
const paramSymbol = getParameterSymbolFromJSDoc(node as JSDocParameterTag);
|
||||
if (paramSymbol) {
|
||||
node = paramSymbol.valueDeclaration;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -14584,24 +14590,14 @@ namespace ts {
|
||||
|
||||
function getObjectTypeInstantiation(type: AnonymousType | DeferredTypeReference, mapper: TypeMapper) {
|
||||
const target = type.objectFlags & ObjectFlags.Instantiated ? type.target! : type;
|
||||
const node = type.objectFlags & ObjectFlags.Reference ? (<TypeReference>type).node! : type.symbol.declarations[0];
|
||||
const links = getNodeLinks(node);
|
||||
const declaration = type.objectFlags & ObjectFlags.Reference ? (<TypeReference>type).node! : type.symbol.declarations[0];
|
||||
const links = getNodeLinks(declaration);
|
||||
let typeParameters = links.outerTypeParameters;
|
||||
if (!typeParameters) {
|
||||
// The first time an anonymous type is instantiated we compute and store a list of the type
|
||||
// parameters that are in scope (and therefore potentially referenced). For type literals that
|
||||
// aren't the right hand side of a generic type alias declaration we optimize by reducing the
|
||||
// set of type parameters to those that are possibly referenced in the literal.
|
||||
let declaration = node;
|
||||
if (isInJSFile(declaration)) {
|
||||
const paramTag = findAncestor(declaration, isJSDocParameterTag);
|
||||
if (paramTag) {
|
||||
const paramSymbol = getParameterSymbolFromJSDoc(paramTag);
|
||||
if (paramSymbol) {
|
||||
declaration = paramSymbol.valueDeclaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
let outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true);
|
||||
if (isJSConstructor(declaration)) {
|
||||
const templateTagParameters = getTypeParametersFromDeclaration(declaration as DeclarationWithTypeParameters);
|
||||
|
||||
21
tests/baselines/reference/paramTagTypeResolution2.symbols
Normal file
21
tests/baselines/reference/paramTagTypeResolution2.symbols
Normal file
@ -0,0 +1,21 @@
|
||||
=== tests/cases/conformance/jsdoc/38572.js ===
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} a
|
||||
* @param {{[K in keyof T]: (value: T[K]) => void }} b
|
||||
*/
|
||||
function f(a, b) {
|
||||
>f : Symbol(f, Decl(38572.js, 0, 0))
|
||||
>a : Symbol(a, Decl(38572.js, 5, 11))
|
||||
>b : Symbol(b, Decl(38572.js, 5, 13))
|
||||
}
|
||||
|
||||
f({ x: 42 }, { x(param) { param.toFixed() } });
|
||||
>f : Symbol(f, Decl(38572.js, 0, 0))
|
||||
>x : Symbol(x, Decl(38572.js, 8, 3))
|
||||
>x : Symbol(x, Decl(38572.js, 8, 14))
|
||||
>param : Symbol(param, Decl(38572.js, 8, 17))
|
||||
>param.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
|
||||
>param : Symbol(param, Decl(38572.js, 8, 17))
|
||||
>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
26
tests/baselines/reference/paramTagTypeResolution2.types
Normal file
26
tests/baselines/reference/paramTagTypeResolution2.types
Normal file
@ -0,0 +1,26 @@
|
||||
=== tests/cases/conformance/jsdoc/38572.js ===
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} a
|
||||
* @param {{[K in keyof T]: (value: T[K]) => void }} b
|
||||
*/
|
||||
function f(a, b) {
|
||||
>f : <T>(a: T, b: { [K in keyof T]: (value: T[K]) => void; }) => void
|
||||
>a : T
|
||||
>b : { [K in keyof T]: (value: T[K]) => void; }
|
||||
}
|
||||
|
||||
f({ x: 42 }, { x(param) { param.toFixed() } });
|
||||
>f({ x: 42 }, { x(param) { param.toFixed() } }) : void
|
||||
>f : <T>(a: T, b: { [K in keyof T]: (value: T[K]) => void; }) => void
|
||||
>{ x: 42 } : { x: number; }
|
||||
>x : number
|
||||
>42 : 42
|
||||
>{ x(param) { param.toFixed() } } : { x(param: number): void; }
|
||||
>x : (param: number) => void
|
||||
>param : number
|
||||
>param.toFixed() : string
|
||||
>param.toFixed : (fractionDigits?: number) => string
|
||||
>param : number
|
||||
>toFixed : (fractionDigits?: number) => string
|
||||
|
||||
14
tests/cases/conformance/jsdoc/paramTagTypeResolution2.ts
Normal file
14
tests/cases/conformance/jsdoc/paramTagTypeResolution2.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// @noEmit: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @Filename: 38572.js
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} a
|
||||
* @param {{[K in keyof T]: (value: T[K]) => void }} b
|
||||
*/
|
||||
function f(a, b) {
|
||||
}
|
||||
|
||||
f({ x: 42 }, { x(param) { param.toFixed() } });
|
||||
Loading…
x
Reference in New Issue
Block a user