mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-23 10:29:01 -06:00
Properly account for type parameters introduced by contextual types (#59516)
This commit is contained in:
parent
5f79e16d33
commit
278cb9489d
@ -12573,7 +12573,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (!node) {
|
||||
return undefined;
|
||||
}
|
||||
switch (node.kind) {
|
||||
const kind = node.kind;
|
||||
switch (kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
@ -12595,15 +12596,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
case SyntaxKind.MappedType:
|
||||
case SyntaxKind.ConditionalType: {
|
||||
const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes);
|
||||
if (node.kind === SyntaxKind.MappedType) {
|
||||
if ((kind === SyntaxKind.FunctionExpression || kind === SyntaxKind.ArrowFunction || isObjectLiteralMethod(node)) && isContextSensitive(node as Expression | MethodDeclaration)) {
|
||||
const signature = firstOrUndefined(getSignaturesOfType(getTypeOfSymbol(getSymbolOfDeclaration(node as FunctionLikeDeclaration)), SignatureKind.Call));
|
||||
if (signature && signature.typeParameters) {
|
||||
return [...(outerTypeParameters || emptyArray), ...signature.typeParameters];
|
||||
}
|
||||
}
|
||||
if (kind === SyntaxKind.MappedType) {
|
||||
return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration((node as MappedTypeNode).typeParameter)));
|
||||
}
|
||||
else if (node.kind === SyntaxKind.ConditionalType) {
|
||||
else if (kind === SyntaxKind.ConditionalType) {
|
||||
return concatenate(outerTypeParameters, getInferTypeParameters(node as ConditionalTypeNode));
|
||||
}
|
||||
const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(node as DeclarationWithTypeParameters));
|
||||
const thisType = includeThisTypes &&
|
||||
(node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) &&
|
||||
(kind === SyntaxKind.ClassDeclaration || kind === SyntaxKind.ClassExpression || kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) &&
|
||||
getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(node as ClassLikeDeclaration | InterfaceDeclaration)).thisType;
|
||||
return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters;
|
||||
}
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
//// [tests/cases/compiler/contextualOuterTypeParameters.ts] ////
|
||||
|
||||
=== contextualOuterTypeParameters.ts ===
|
||||
// https://github.com/microsoft/TypeScript/issues/59450
|
||||
|
||||
declare function f(fun: <T>(t: T) => void): void
|
||||
>f : Symbol(f, Decl(contextualOuterTypeParameters.ts, 0, 0))
|
||||
>fun : Symbol(fun, Decl(contextualOuterTypeParameters.ts, 2, 19))
|
||||
>T : Symbol(T, Decl(contextualOuterTypeParameters.ts, 2, 25))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 2, 28))
|
||||
>T : Symbol(T, Decl(contextualOuterTypeParameters.ts, 2, 25))
|
||||
|
||||
f(t => {
|
||||
>f : Symbol(f, Decl(contextualOuterTypeParameters.ts, 0, 0))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 4, 2))
|
||||
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
>isArray : Symbol(isArray, Decl(contextualOuterTypeParameters.ts, 4, 8))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 4, 2))
|
||||
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
>IsObject : Symbol(IsObject, Decl(contextualOuterTypeParameters.ts, 5, 64))
|
||||
>x : Symbol(x, Decl(contextualOuterTypeParameters.ts, 6, 21))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 4, 2))
|
||||
>x : Symbol(x, Decl(contextualOuterTypeParameters.ts, 6, 45))
|
||||
|
||||
});
|
||||
|
||||
const fn1: <T>(x: T) => void = t => {
|
||||
>fn1 : Symbol(fn1, Decl(contextualOuterTypeParameters.ts, 9, 5))
|
||||
>T : Symbol(T, Decl(contextualOuterTypeParameters.ts, 9, 12))
|
||||
>x : Symbol(x, Decl(contextualOuterTypeParameters.ts, 9, 15))
|
||||
>T : Symbol(T, Decl(contextualOuterTypeParameters.ts, 9, 12))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 9, 30))
|
||||
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
>isArray : Symbol(isArray, Decl(contextualOuterTypeParameters.ts, 9, 37))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 9, 30))
|
||||
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
>IsObject : Symbol(IsObject, Decl(contextualOuterTypeParameters.ts, 10, 64))
|
||||
>x : Symbol(x, Decl(contextualOuterTypeParameters.ts, 11, 21))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 9, 30))
|
||||
>x : Symbol(x, Decl(contextualOuterTypeParameters.ts, 11, 45))
|
||||
|
||||
};
|
||||
|
||||
const fn2: <T>(x: T) => void = function test(t) {
|
||||
>fn2 : Symbol(fn2, Decl(contextualOuterTypeParameters.ts, 14, 5))
|
||||
>T : Symbol(T, Decl(contextualOuterTypeParameters.ts, 14, 12))
|
||||
>x : Symbol(x, Decl(contextualOuterTypeParameters.ts, 14, 15))
|
||||
>T : Symbol(T, Decl(contextualOuterTypeParameters.ts, 14, 12))
|
||||
>test : Symbol(test, Decl(contextualOuterTypeParameters.ts, 14, 30))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 14, 45))
|
||||
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
>isArray : Symbol(isArray, Decl(contextualOuterTypeParameters.ts, 14, 49))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 14, 45))
|
||||
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
>IsObject : Symbol(IsObject, Decl(contextualOuterTypeParameters.ts, 15, 64))
|
||||
>x : Symbol(x, Decl(contextualOuterTypeParameters.ts, 16, 21))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 14, 45))
|
||||
>x : Symbol(x, Decl(contextualOuterTypeParameters.ts, 16, 45))
|
||||
|
||||
};
|
||||
|
||||
const obj: { f: <T>(x: T) => void } = {
|
||||
>obj : Symbol(obj, Decl(contextualOuterTypeParameters.ts, 19, 5))
|
||||
>f : Symbol(f, Decl(contextualOuterTypeParameters.ts, 19, 12))
|
||||
>T : Symbol(T, Decl(contextualOuterTypeParameters.ts, 19, 17))
|
||||
>x : Symbol(x, Decl(contextualOuterTypeParameters.ts, 19, 20))
|
||||
>T : Symbol(T, Decl(contextualOuterTypeParameters.ts, 19, 17))
|
||||
|
||||
f(t) {
|
||||
>f : Symbol(f, Decl(contextualOuterTypeParameters.ts, 19, 39))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 20, 6))
|
||||
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
>isArray : Symbol(isArray, Decl(contextualOuterTypeParameters.ts, 20, 10))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 20, 6))
|
||||
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
>IsObject : Symbol(IsObject, Decl(contextualOuterTypeParameters.ts, 21, 68))
|
||||
>x : Symbol(x, Decl(contextualOuterTypeParameters.ts, 22, 25))
|
||||
>t : Symbol(t, Decl(contextualOuterTypeParameters.ts, 20, 6))
|
||||
>x : Symbol(x, Decl(contextualOuterTypeParameters.ts, 22, 49))
|
||||
}
|
||||
};
|
||||
|
||||
165
tests/baselines/reference/contextualOuterTypeParameters.types
Normal file
165
tests/baselines/reference/contextualOuterTypeParameters.types
Normal file
@ -0,0 +1,165 @@
|
||||
//// [tests/cases/compiler/contextualOuterTypeParameters.ts] ////
|
||||
|
||||
=== contextualOuterTypeParameters.ts ===
|
||||
// https://github.com/microsoft/TypeScript/issues/59450
|
||||
|
||||
declare function f(fun: <T>(t: T) => void): void
|
||||
>f : (fun: <T>(t: T) => void) => void
|
||||
> : ^ ^^ ^^^^^
|
||||
>fun : <T>(t: T) => void
|
||||
> : ^ ^^ ^^ ^^^^^
|
||||
>t : T
|
||||
> : ^
|
||||
|
||||
f(t => {
|
||||
>f(t => { type isArray = (typeof t)[] extends string[] ? true : false; type IsObject = { x: typeof t } extends { x: string } ? true : false;}) : void
|
||||
> : ^^^^
|
||||
>f : (fun: <T>(t: T) => void) => void
|
||||
> : ^ ^^ ^^^^^
|
||||
>t => { type isArray = (typeof t)[] extends string[] ? true : false; type IsObject = { x: typeof t } extends { x: string } ? true : false;} : <T>(t: T) => void
|
||||
> : ^ ^^ ^^^^^^^^^^^^
|
||||
>t : T
|
||||
> : ^
|
||||
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
>isArray : T[] extends string[] ? true : false
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>t : T
|
||||
> : ^
|
||||
>true : true
|
||||
> : ^^^^
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
>IsObject : { x: typeof t; } extends { x: string; } ? true : false
|
||||
> : ^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
|
||||
>x : T
|
||||
> : ^
|
||||
>t : T
|
||||
> : ^
|
||||
>x : string
|
||||
> : ^^^^^^
|
||||
>true : true
|
||||
> : ^^^^
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
});
|
||||
|
||||
const fn1: <T>(x: T) => void = t => {
|
||||
>fn1 : <T>(x: T) => void
|
||||
> : ^ ^^ ^^ ^^^^^
|
||||
>x : T
|
||||
> : ^
|
||||
>t => { type isArray = (typeof t)[] extends string[] ? true : false; type IsObject = { x: typeof t } extends { x: string } ? true : false;} : <T>(t: T) => void
|
||||
> : ^ ^^ ^^^^^^^^^^^^
|
||||
>t : T
|
||||
> : ^
|
||||
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
>isArray : T[] extends string[] ? true : false
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>t : T
|
||||
> : ^
|
||||
>true : true
|
||||
> : ^^^^
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
>IsObject : { x: typeof t; } extends { x: string; } ? true : false
|
||||
> : ^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
|
||||
>x : T
|
||||
> : ^
|
||||
>t : T
|
||||
> : ^
|
||||
>x : string
|
||||
> : ^^^^^^
|
||||
>true : true
|
||||
> : ^^^^
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
};
|
||||
|
||||
const fn2: <T>(x: T) => void = function test(t) {
|
||||
>fn2 : <T>(x: T) => void
|
||||
> : ^ ^^ ^^ ^^^^^
|
||||
>x : T
|
||||
> : ^
|
||||
>function test(t) { type isArray = (typeof t)[] extends string[] ? true : false; type IsObject = { x: typeof t } extends { x: string } ? true : false;} : <T>(t: T) => void
|
||||
> : ^ ^^ ^^^^^^^^^^^^
|
||||
>test : <T>(t: T) => void
|
||||
> : ^ ^^ ^^^^^^^^^^^^
|
||||
>t : T
|
||||
> : ^
|
||||
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
>isArray : T[] extends string[] ? true : false
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>t : T
|
||||
> : ^
|
||||
>true : true
|
||||
> : ^^^^
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
>IsObject : { x: typeof t; } extends { x: string; } ? true : false
|
||||
> : ^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
|
||||
>x : T
|
||||
> : ^
|
||||
>t : T
|
||||
> : ^
|
||||
>x : string
|
||||
> : ^^^^^^
|
||||
>true : true
|
||||
> : ^^^^
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
};
|
||||
|
||||
const obj: { f: <T>(x: T) => void } = {
|
||||
>obj : { f: <T>(x: T) => void; }
|
||||
> : ^^^^^ ^^^
|
||||
>f : <T>(x: T) => void
|
||||
> : ^ ^^ ^^ ^^^^^
|
||||
>x : T
|
||||
> : ^
|
||||
>{ f(t) { type isArray = (typeof t)[] extends string[] ? true : false; type IsObject = { x: typeof t } extends { x: string } ? true : false; }} : { f<T>(t: T): void; }
|
||||
> : ^^^^ ^^ ^^^^^^^^^^^^^
|
||||
|
||||
f(t) {
|
||||
>f : <T>(t: T) => void
|
||||
> : ^ ^^ ^^^^^^^^^^^^
|
||||
>t : T
|
||||
> : ^
|
||||
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
>isArray : T[] extends string[] ? true : false
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>t : T
|
||||
> : ^
|
||||
>true : true
|
||||
> : ^^^^
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
>IsObject : { x: typeof t; } extends { x: string; } ? true : false
|
||||
> : ^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
|
||||
>x : T
|
||||
> : ^
|
||||
>t : T
|
||||
> : ^
|
||||
>x : string
|
||||
> : ^^^^^^
|
||||
>true : true
|
||||
> : ^^^^
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
}
|
||||
};
|
||||
|
||||
28
tests/cases/compiler/contextualOuterTypeParameters.ts
Normal file
28
tests/cases/compiler/contextualOuterTypeParameters.ts
Normal file
@ -0,0 +1,28 @@
|
||||
// @strict: true
|
||||
// @noemit: true
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/59450
|
||||
|
||||
declare function f(fun: <T>(t: T) => void): void
|
||||
|
||||
f(t => {
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
});
|
||||
|
||||
const fn1: <T>(x: T) => void = t => {
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
};
|
||||
|
||||
const fn2: <T>(x: T) => void = function test(t) {
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
};
|
||||
|
||||
const obj: { f: <T>(x: T) => void } = {
|
||||
f(t) {
|
||||
type isArray = (typeof t)[] extends string[] ? true : false;
|
||||
type IsObject = { x: typeof t } extends { x: string } ? true : false;
|
||||
}
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user