Add 'extends' clause to 'infer' type

This commit is contained in:
Ron Buckton
2022-03-04 10:31:21 -08:00
parent 0a24dee97d
commit bafe1931a3
23 changed files with 1017 additions and 55 deletions
+19 -3
View File
@@ -35335,6 +35335,22 @@ namespace ts {
grammarErrorOnNode(node, Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type);
}
checkSourceElement(node.typeParameter);
const symbol = getSymbolOfNode(node.typeParameter);
if (symbol.declarations && symbol.declarations.length > 1) {
const links = getSymbolLinks(symbol);
if (!links.typeParametersChecked) {
links.typeParametersChecked = true;
const typeParameter = getDeclaredTypeOfTypeParameter(symbol);
const declarations: TypeParameterDeclaration[] = getDeclarationsOfKind(symbol, SyntaxKind.TypeParameter);
if (!areTypeParametersIdentical(declarations, [typeParameter], decl => [decl])) {
// Report an error on every conflicting declaration.
const name = symbolToString(symbol);
for (const declaration of declarations) {
error(declaration.name, Diagnostics.All_declarations_of_0_must_have_identical_constraints, name);
}
}
}
}
registerForUnusedIdentifiersCheck(node);
}
@@ -38811,7 +38827,7 @@ namespace ts {
}
const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType;
if (!areTypeParametersIdentical(declarations, type.localTypeParameters!)) {
if (!areTypeParametersIdentical(declarations, type.localTypeParameters!, getEffectiveTypeParameterDeclarations)) {
// Report an error on every conflicting declaration.
const name = symbolToString(symbol);
for (const declaration of declarations) {
@@ -38821,13 +38837,13 @@ namespace ts {
}
}
function areTypeParametersIdentical(declarations: readonly (ClassDeclaration | InterfaceDeclaration)[], targetParameters: TypeParameter[]) {
function areTypeParametersIdentical<T extends DeclarationWithTypeParameters | TypeParameterDeclaration>(declarations: readonly T[], targetParameters: TypeParameter[], getTypeParameterDeclarations: (node: T) => readonly TypeParameterDeclaration[]) {
const maxTypeArgumentCount = length(targetParameters);
const minTypeArgumentCount = getMinTypeArgumentCount(targetParameters);
for (const declaration of declarations) {
// If this declaration has too few or too many type parameters, we report an error
const sourceParameters = getEffectiveTypeParameterDeclarations(declaration);
const sourceParameters = getTypeParameterDeclarations(declaration);
const numTypeParameters = sourceParameters.length;
if (numTypeParameters < minTypeArgumentCount || numTypeParameters > maxTypeArgumentCount) {
return false;
+4
View File
@@ -3405,6 +3405,10 @@
"category": "Error",
"code": 2837
},
"All declarations of '{0}' must have identical constraints.": {
"category": "Error",
"code": 2838
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
+1 -1
View File
@@ -1989,7 +1989,7 @@ namespace ts {
// @api
function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) {
const node = createBaseNode<ConditionalTypeNode>(SyntaxKind.ConditionalType);
node.checkType = parenthesizerRules().parenthesizeMemberOfConditionalType(checkType);
node.checkType = parenthesizerRules().parenthesizeCheckTypeOfConditionalType(checkType);
node.extendsType = parenthesizerRules().parenthesizeMemberOfConditionalType(extendsType);
node.trueType = trueType;
node.falseType = falseType;
@@ -25,6 +25,7 @@ namespace ts {
parenthesizeExpressionForDisallowedComma,
parenthesizeExpressionOfExpressionStatement,
parenthesizeConciseBodyOfArrowFunction,
parenthesizeCheckTypeOfConditionalType,
parenthesizeMemberOfConditionalType,
parenthesizeMemberOfElementType,
parenthesizeElementTypeOfArrayType,
@@ -388,6 +389,11 @@ namespace ts {
return body;
}
function parenthesizeCheckTypeOfConditionalType(member: TypeNode): TypeNode {
return isInferTypeNode(member) ? factory.createParenthesizedType(member) :
parenthesizeMemberOfConditionalType(member);
}
function parenthesizeMemberOfConditionalType(member: TypeNode): TypeNode {
return member.kind === SyntaxKind.ConditionalType ? factory.createParenthesizedType(member) : member;
}
@@ -446,6 +452,7 @@ namespace ts {
parenthesizeExpressionForDisallowedComma: identity,
parenthesizeExpressionOfExpressionStatement: identity,
parenthesizeConciseBodyOfArrowFunction: identity,
parenthesizeCheckTypeOfConditionalType: identity,
parenthesizeMemberOfConditionalType: identity,
parenthesizeMemberOfElementType: identity,
parenthesizeElementTypeOfArrayType: identity,
+6 -14
View File
@@ -3077,6 +3077,10 @@ namespace ts {
}
function parseTypeParameter(): TypeParameterDeclaration {
return parseTypeParameterWorker(/*canHaveDefault*/ true);
}
function parseTypeParameterWorker(canHaveDefault: boolean): TypeParameterDeclaration {
const pos = getNodePos();
const name = parseIdentifier();
let constraint: TypeNode | undefined;
@@ -3101,7 +3105,7 @@ namespace ts {
}
}
const defaultType = parseOptional(SyntaxKind.EqualsToken) ? parseType() : undefined;
const defaultType = canHaveDefault && parseOptional(SyntaxKind.EqualsToken) ? parseType() : undefined;
const node = factory.createTypeParameterDeclaration(name, constraint, defaultType);
node.expression = expression;
return finishNode(node, pos);
@@ -3859,22 +3863,10 @@ namespace ts {
return finishNode(factory.createTypeOperatorNode(operator, parseTypeOperatorOrHigher()), pos);
}
function parseTypeParameterOfInferType() {
const pos = getNodePos();
return finishNode(
factory.createTypeParameterDeclaration(
parseIdentifier(),
/*constraint*/ undefined,
/*defaultType*/ undefined
),
pos
);
}
function parseInferType(): InferTypeNode {
const pos = getNodePos();
parseExpected(SyntaxKind.InferKeyword);
return finishNode(factory.createInferTypeNode(parseTypeParameterOfInferType()), pos);
return finishNode(factory.createInferTypeNode(parseTypeParameterWorker(/*canHaveDefault*/ false)), pos);
}
function parseTypeOperatorOrHigher(): TypeNode {
+1
View File
@@ -7090,6 +7090,7 @@ namespace ts {
parenthesizeExpressionOfExpressionStatement(expression: Expression): Expression;
parenthesizeConciseBodyOfArrowFunction(body: Expression): Expression;
parenthesizeConciseBodyOfArrowFunction(body: ConciseBody): ConciseBody;
parenthesizeCheckTypeOfConditionalType(member: TypeNode): TypeNode;
parenthesizeMemberOfConditionalType(member: TypeNode): TypeNode;
parenthesizeMemberOfElementType(member: TypeNode): TypeNode;
parenthesizeElementTypeOfArrayType(member: TypeNode): TypeNode;
@@ -8,9 +8,9 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(55,25): error TS2344: T
tests/cases/conformance/types/conditional/inferTypes1.ts(56,25): error TS2344: Type 'Function' does not satisfy the constraint '(x: any) => any'.
Type 'Function' provides no match for the signature '(x: any): any'.
tests/cases/conformance/types/conditional/inferTypes1.ts(82,12): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
tests/cases/conformance/types/conditional/inferTypes1.ts(83,15): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
tests/cases/conformance/types/conditional/inferTypes1.ts(83,41): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
tests/cases/conformance/types/conditional/inferTypes1.ts(83,51): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
tests/cases/conformance/types/conditional/inferTypes1.ts(83,16): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
tests/cases/conformance/types/conditional/inferTypes1.ts(83,43): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
tests/cases/conformance/types/conditional/inferTypes1.ts(83,53): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
tests/cases/conformance/types/conditional/inferTypes1.ts(84,15): error TS2304: Cannot find name 'U'.
tests/cases/conformance/types/conditional/inferTypes1.ts(84,15): error TS4081: Exported type alias 'T62' has or is using private name 'U'.
tests/cases/conformance/types/conditional/inferTypes1.ts(84,43): error TS2304: Cannot find name 'U'.
@@ -120,12 +120,12 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(153,40): error TS2322:
type T60 = infer U; // Error
~~~~~~~
!!! error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
type T61<T> = infer A extends infer B ? infer C : infer D; // Error
~~~~~~~
type T61<T> = (infer A) extends infer B ? infer C : infer D; // Error
~~~~~~~
!!! error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
~~~~~~~
~~~~~~~
!!! error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
~~~~~~~
~~~~~~~
!!! error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
type T62<T> = U extends (infer U)[] ? U : U; // Error
~
@@ -136,7 +136,7 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(153,40): error TS2322:
!!! error TS2304: Cannot find name 'U'.
~
!!! error TS4081: Exported type alias 'T62' has or is using private name 'U'.
type T63<T> = T extends (infer A extends infer B ? infer C : infer D) ? string : number;
type T63<T> = T extends ((infer A) extends infer B ? infer C : infer D) ? string : number;
type T70<T extends string> = { x: T };
type T71<T> = T extends T70<infer U> ? T70<U> : never;
+2 -2
View File
@@ -81,9 +81,9 @@ type T53 = X3<{ a: (x: number) => void, b: (x: string) => void }>; // never
type T54 = X3<{ a: (x: number) => void, b: () => void }>; // number
type T60 = infer U; // Error
type T61<T> = infer A extends infer B ? infer C : infer D; // Error
type T61<T> = (infer A) extends infer B ? infer C : infer D; // Error
type T62<T> = U extends (infer U)[] ? U : U; // Error
type T63<T> = T extends (infer A extends infer B ? infer C : infer D) ? string : number;
type T63<T> = T extends ((infer A) extends infer B ? infer C : infer D) ? string : number;
type T70<T extends string> = { x: T };
type T71<T> = T extends T70<infer U> ? T70<U> : never;
+16 -16
View File
@@ -349,33 +349,33 @@ type T60 = infer U; // Error
>T60 : Symbol(T60, Decl(inferTypes1.ts, 79, 57))
>U : Symbol(U, Decl(inferTypes1.ts, 81, 16))
type T61<T> = infer A extends infer B ? infer C : infer D; // Error
type T61<T> = (infer A) extends infer B ? infer C : infer D; // Error
>T61 : Symbol(T61, Decl(inferTypes1.ts, 81, 19))
>T : Symbol(T, Decl(inferTypes1.ts, 82, 9))
>A : Symbol(A, Decl(inferTypes1.ts, 82, 19))
>B : Symbol(B, Decl(inferTypes1.ts, 82, 35))
>C : Symbol(C, Decl(inferTypes1.ts, 82, 45))
>D : Symbol(D, Decl(inferTypes1.ts, 82, 55))
>A : Symbol(A, Decl(inferTypes1.ts, 82, 20))
>B : Symbol(B, Decl(inferTypes1.ts, 82, 37))
>C : Symbol(C, Decl(inferTypes1.ts, 82, 47))
>D : Symbol(D, Decl(inferTypes1.ts, 82, 57))
type T62<T> = U extends (infer U)[] ? U : U; // Error
>T62 : Symbol(T62, Decl(inferTypes1.ts, 82, 58))
>T62 : Symbol(T62, Decl(inferTypes1.ts, 82, 60))
>T : Symbol(T, Decl(inferTypes1.ts, 83, 9))
>U : Symbol(U)
>U : Symbol(U, Decl(inferTypes1.ts, 83, 30))
>U : Symbol(U, Decl(inferTypes1.ts, 83, 30))
>U : Symbol(U)
type T63<T> = T extends (infer A extends infer B ? infer C : infer D) ? string : number;
type T63<T> = T extends ((infer A) extends infer B ? infer C : infer D) ? string : number;
>T63 : Symbol(T63, Decl(inferTypes1.ts, 83, 44))
>T : Symbol(T, Decl(inferTypes1.ts, 84, 9))
>T : Symbol(T, Decl(inferTypes1.ts, 84, 9))
>A : Symbol(A, Decl(inferTypes1.ts, 84, 30))
>B : Symbol(B, Decl(inferTypes1.ts, 84, 46))
>C : Symbol(C, Decl(inferTypes1.ts, 84, 56))
>D : Symbol(D, Decl(inferTypes1.ts, 84, 66))
>A : Symbol(A, Decl(inferTypes1.ts, 84, 31))
>B : Symbol(B, Decl(inferTypes1.ts, 84, 48))
>C : Symbol(C, Decl(inferTypes1.ts, 84, 58))
>D : Symbol(D, Decl(inferTypes1.ts, 84, 68))
type T70<T extends string> = { x: T };
>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 88))
>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 90))
>T : Symbol(T, Decl(inferTypes1.ts, 86, 9))
>x : Symbol(x, Decl(inferTypes1.ts, 86, 30))
>T : Symbol(T, Decl(inferTypes1.ts, 86, 9))
@@ -384,9 +384,9 @@ type T71<T> = T extends T70<infer U> ? T70<U> : never;
>T71 : Symbol(T71, Decl(inferTypes1.ts, 86, 38))
>T : Symbol(T, Decl(inferTypes1.ts, 87, 9))
>T : Symbol(T, Decl(inferTypes1.ts, 87, 9))
>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 88))
>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 90))
>U : Symbol(U, Decl(inferTypes1.ts, 87, 33))
>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 88))
>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 90))
>U : Symbol(U, Decl(inferTypes1.ts, 87, 33))
type T72<T extends number> = { y: T };
@@ -401,7 +401,7 @@ type T73<T> = T extends T72<infer U> ? T70<U> : never; // Error
>T : Symbol(T, Decl(inferTypes1.ts, 90, 9))
>T72 : Symbol(T72, Decl(inferTypes1.ts, 87, 54))
>U : Symbol(U, Decl(inferTypes1.ts, 90, 33))
>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 88))
>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 90))
>U : Symbol(U, Decl(inferTypes1.ts, 90, 33))
type T74<T extends number, U extends string> = { x: T, y: U };
@@ -420,7 +420,7 @@ type T75<T> = T extends T74<infer U, infer U> ? T70<U> | T72<U> | T74<U, U> : ne
>T74 : Symbol(T74, Decl(inferTypes1.ts, 90, 54))
>U : Symbol(U, Decl(inferTypes1.ts, 93, 33), Decl(inferTypes1.ts, 93, 42))
>U : Symbol(U, Decl(inferTypes1.ts, 93, 33), Decl(inferTypes1.ts, 93, 42))
>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 88))
>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 90))
>U : Symbol(U, Decl(inferTypes1.ts, 93, 33), Decl(inferTypes1.ts, 93, 42))
>T72 : Symbol(T72, Decl(inferTypes1.ts, 87, 54))
>U : Symbol(U, Decl(inferTypes1.ts, 93, 33), Decl(inferTypes1.ts, 93, 42))
+2 -2
View File
@@ -253,13 +253,13 @@ type T54 = X3<{ a: (x: number) => void, b: () => void }>; // number
type T60 = infer U; // Error
>T60 : U
type T61<T> = infer A extends infer B ? infer C : infer D; // Error
type T61<T> = (infer A) extends infer B ? infer C : infer D; // Error
>T61 : T61<T>
type T62<T> = U extends (infer U)[] ? U : U; // Error
>T62 : any
type T63<T> = T extends (infer A extends infer B ? infer C : infer D) ? string : number;
type T63<T> = T extends ((infer A) extends infer B ? infer C : infer D) ? string : number;
>T63 : T63<T>
type T70<T extends string> = { x: T };
+1 -1
View File
@@ -49,5 +49,5 @@ export declare function foo2<T>(obj: T): T extends {
[K in keyof BadNested<infer P>]: BadNested<infer P>[K];
} ? P : never;
export declare function bar2<T>(obj: T): T extends {
x: infer P extends number ? infer P : string;
x: (infer P) extends number ? infer P : string;
} ? P : never;
+4 -4
View File
@@ -20,16 +20,16 @@ export type BadNested<T> = { x: T extends number ? T : string };
>x : T extends number ? T : string
export declare function foo2<T>(obj: T): T extends { [K in keyof BadNested<infer P>]: BadNested<infer P>[K] } ? P : never;
>foo2 : <T>(obj: T) => T extends { x: infer P extends number ? infer P : string; } ? P : never
>foo2 : <T>(obj: T) => T extends { x: (infer P) extends number ? infer P : string; } ? P : never
>obj : T
export function bar2<T>(obj: T) {
>bar2 : <T>(obj: T) => T extends { x: infer P extends number ? infer P : string; } ? P : never
>bar2 : <T>(obj: T) => T extends { x: (infer P) extends number ? infer P : string; } ? P : never
>obj : T
return foo2(obj);
>foo2(obj) : T extends { x: infer P extends number ? infer P : string; } ? P : never
>foo2 : <T>(obj: T) => T extends { x: infer P extends number ? infer P : string; } ? P : never
>foo2(obj) : T extends { x: (infer P) extends number ? infer P : string; } ? P : never
>foo2 : <T>(obj: T) => T extends { x: (infer P) extends number ? infer P : string; } ? P : never
>obj : T
}
@@ -0,0 +1,213 @@
//// [inferTypesWithExtends1.ts]
// infer to tuple element
type X1<T extends any[]> =
T extends [infer U extends string] ? ["string", U] :
T extends [infer U extends number] ? ["number", U] :
never;
type X1_T1 = X1<["a"]>; // ["string", "a"]
type X1_T2 = X1<[1]>; // ["number", 1]
type X1_T3 = X1<[object]>; // never
// infer to argument
type X2<T extends (...args: any[]) => void> =
T extends (a: infer U extends string) => void ? ["string", U] :
T extends (a: infer U extends number) => void ? ["number", U] :
never;
type X2_T1 = X2<(a: "a") => void>; // ["string", "a"]
type X2_T2 = X2<(a: 1) => void>; // ["number", 1]
type X2_T3 = X2<(a: object) => void>; // never
// infer to return type
type X3<T extends (...args: any[]) => any> =
T extends (...args: any[]) => infer U extends string ? ["string", U] :
T extends (...args: any[]) => infer U extends number ? ["number", U] :
never;
type X3_T1 = X3<() => "a">; // ["string", "a"]
type X3_T2 = X3<() => 1>; // ["number", 1]
type X3_T3 = X3<() => object>; // never
// infer to instance type
type X4<T extends new (...args: any[]) => any> =
T extends new (...args: any[]) => infer U extends { a: string } ? ["string", U] :
T extends new (...args: any[]) => infer U extends { a: number } ? ["number", U] :
never;
type X4_T1 = X4<new () => { a: "a" }>; // ["string", { a: "a" }]
type X4_T2 = X4<new () => { a: 1 }>; // ["number", { a: 1 }]
type X4_T3 = X4<new () => { a: object }>; // never
// infer to type argument
type X5<T> =
T extends Promise<infer U extends string> ? ["string", U] :
T extends Promise<infer U extends number> ? ["number", U] :
never;
type X5_T1 = X5<Promise<"a" | "b">>; // ["string", "a" | "b"]
type X5_T2 = X5<Promise<1 | 2>>; // ["number", 1 | 2]
type X5_T3 = X5<Promise<1n | 2n>>; // never
// infer to property type
type X6<T> =
T extends { a: infer U extends string } ? ["string", U] :
T extends { a: infer U extends number } ? ["number", U] :
never;
type X6_T1 = X6<{ a: "a" }>; // ["string", "a"]
type X6_T2 = X6<{ a: 1 }>; // ["number", 1]
type X6_T3 = X6<{ a: object }>; // never
// infer twice with same constraint
type X7<T> =
T extends { a: infer U extends string, b: infer U extends string } ? ["string", U] :
T extends { a: infer U extends number, b: infer U extends number } ? ["number", U] :
never;
type X7_T1 = X7<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
type X7_T2 = X7<{ a: 1, b: 2 }>; // ["number", 1 | 2]
type X7_T3 = X7<{ a: object, b: object }>; // never
type X7_T4 = X7<{ a: "a", b: 1 }>; // never
// infer twice with missing second constraint (same behavior as class/interface)
type X8<T> =
T extends { a: infer U extends string, b: infer U } ? ["string", U] :
T extends { a: infer U extends number, b: infer U } ? ["number", U] :
never;
type X8_T1 = X8<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
type X8_T2 = X8<{ a: 1, b: 2 }>; // ["number", 1 | 2]
type X8_T3 = X8<{ a: object, b: object }>; // never
type X8_T4 = X8<{ a: "a", b: 1 }>; // never
// infer twice with missing first constraint (same behavior as class/interface)
type X9<T> =
T extends { a: infer U, b: infer U extends string } ? ["string", U] :
T extends { a: infer U, b: infer U extends number } ? ["number", U] :
never;
type X9_T1 = X9<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
type X9_T2 = X9<{ a: 1, b: 2 }>; // ["number", 1 | 2]
type X9_T3 = X9<{ a: object, b: object }>; // never
type X9_T4 = X9<{ a: "a", b: 1 }>; // never
//// [inferTypesWithExtends1.js]
"use strict";
//// [inferTypesWithExtends1.d.ts]
declare type X1<T extends any[]> = T extends [infer U extends string] ? ["string", U] : T extends [infer U extends number] ? ["number", U] : never;
declare type X1_T1 = X1<["a"]>;
declare type X1_T2 = X1<[1]>;
declare type X1_T3 = X1<[object]>;
declare type X2<T extends (...args: any[]) => void> = T extends (a: infer U extends string) => void ? ["string", U] : T extends (a: infer U extends number) => void ? ["number", U] : never;
declare type X2_T1 = X2<(a: "a") => void>;
declare type X2_T2 = X2<(a: 1) => void>;
declare type X2_T3 = X2<(a: object) => void>;
declare type X3<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer U extends string ? ["string", U] : T extends (...args: any[]) => infer U extends number ? ["number", U] : never;
declare type X3_T1 = X3<() => "a">;
declare type X3_T2 = X3<() => 1>;
declare type X3_T3 = X3<() => object>;
declare type X4<T extends new (...args: any[]) => any> = T extends new (...args: any[]) => infer U extends {
a: string;
} ? ["string", U] : T extends new (...args: any[]) => infer U extends {
a: number;
} ? ["number", U] : never;
declare type X4_T1 = X4<new () => {
a: "a";
}>;
declare type X4_T2 = X4<new () => {
a: 1;
}>;
declare type X4_T3 = X4<new () => {
a: object;
}>;
declare type X5<T> = T extends Promise<infer U extends string> ? ["string", U] : T extends Promise<infer U extends number> ? ["number", U] : never;
declare type X5_T1 = X5<Promise<"a" | "b">>;
declare type X5_T2 = X5<Promise<1 | 2>>;
declare type X5_T3 = X5<Promise<1n | 2n>>;
declare type X6<T> = T extends {
a: infer U extends string;
} ? ["string", U] : T extends {
a: infer U extends number;
} ? ["number", U] : never;
declare type X6_T1 = X6<{
a: "a";
}>;
declare type X6_T2 = X6<{
a: 1;
}>;
declare type X6_T3 = X6<{
a: object;
}>;
declare type X7<T> = T extends {
a: infer U extends string;
b: infer U extends string;
} ? ["string", U] : T extends {
a: infer U extends number;
b: infer U extends number;
} ? ["number", U] : never;
declare type X7_T1 = X7<{
a: "a";
b: "b";
}>;
declare type X7_T2 = X7<{
a: 1;
b: 2;
}>;
declare type X7_T3 = X7<{
a: object;
b: object;
}>;
declare type X7_T4 = X7<{
a: "a";
b: 1;
}>;
declare type X8<T> = T extends {
a: infer U extends string;
b: infer U;
} ? ["string", U] : T extends {
a: infer U extends number;
b: infer U;
} ? ["number", U] : never;
declare type X8_T1 = X8<{
a: "a";
b: "b";
}>;
declare type X8_T2 = X8<{
a: 1;
b: 2;
}>;
declare type X8_T3 = X8<{
a: object;
b: object;
}>;
declare type X8_T4 = X8<{
a: "a";
b: 1;
}>;
declare type X9<T> = T extends {
a: infer U;
b: infer U extends string;
} ? ["string", U] : T extends {
a: infer U;
b: infer U extends number;
} ? ["number", U] : never;
declare type X9_T1 = X9<{
a: "a";
b: "b";
}>;
declare type X9_T2 = X9<{
a: 1;
b: 2;
}>;
declare type X9_T3 = X9<{
a: object;
b: object;
}>;
declare type X9_T4 = X9<{
a: "a";
b: 1;
}>;
@@ -0,0 +1,343 @@
=== tests/cases/conformance/types/conditional/inferTypesWithExtends1.ts ===
// infer to tuple element
type X1<T extends any[]> =
>X1 : Symbol(X1, Decl(inferTypesWithExtends1.ts, 0, 0))
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 1, 8))
T extends [infer U extends string] ? ["string", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 1, 8))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 2, 20))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 2, 20))
T extends [infer U extends number] ? ["number", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 1, 8))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 3, 20))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 3, 20))
never;
type X1_T1 = X1<["a"]>; // ["string", "a"]
>X1_T1 : Symbol(X1_T1, Decl(inferTypesWithExtends1.ts, 4, 10))
>X1 : Symbol(X1, Decl(inferTypesWithExtends1.ts, 0, 0))
type X1_T2 = X1<[1]>; // ["number", 1]
>X1_T2 : Symbol(X1_T2, Decl(inferTypesWithExtends1.ts, 6, 23))
>X1 : Symbol(X1, Decl(inferTypesWithExtends1.ts, 0, 0))
type X1_T3 = X1<[object]>; // never
>X1_T3 : Symbol(X1_T3, Decl(inferTypesWithExtends1.ts, 7, 21))
>X1 : Symbol(X1, Decl(inferTypesWithExtends1.ts, 0, 0))
// infer to argument
type X2<T extends (...args: any[]) => void> =
>X2 : Symbol(X2, Decl(inferTypesWithExtends1.ts, 8, 26))
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 11, 8))
>args : Symbol(args, Decl(inferTypesWithExtends1.ts, 11, 19))
T extends (a: infer U extends string) => void ? ["string", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 11, 8))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 12, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 12, 23))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 12, 23))
T extends (a: infer U extends number) => void ? ["number", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 11, 8))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 13, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 13, 23))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 13, 23))
never;
type X2_T1 = X2<(a: "a") => void>; // ["string", "a"]
>X2_T1 : Symbol(X2_T1, Decl(inferTypesWithExtends1.ts, 14, 10))
>X2 : Symbol(X2, Decl(inferTypesWithExtends1.ts, 8, 26))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 16, 17))
type X2_T2 = X2<(a: 1) => void>; // ["number", 1]
>X2_T2 : Symbol(X2_T2, Decl(inferTypesWithExtends1.ts, 16, 34))
>X2 : Symbol(X2, Decl(inferTypesWithExtends1.ts, 8, 26))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 17, 17))
type X2_T3 = X2<(a: object) => void>; // never
>X2_T3 : Symbol(X2_T3, Decl(inferTypesWithExtends1.ts, 17, 32))
>X2 : Symbol(X2, Decl(inferTypesWithExtends1.ts, 8, 26))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 18, 17))
// infer to return type
type X3<T extends (...args: any[]) => any> =
>X3 : Symbol(X3, Decl(inferTypesWithExtends1.ts, 18, 37))
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 21, 8))
>args : Symbol(args, Decl(inferTypesWithExtends1.ts, 21, 19))
T extends (...args: any[]) => infer U extends string ? ["string", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 21, 8))
>args : Symbol(args, Decl(inferTypesWithExtends1.ts, 22, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 22, 39))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 22, 39))
T extends (...args: any[]) => infer U extends number ? ["number", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 21, 8))
>args : Symbol(args, Decl(inferTypesWithExtends1.ts, 23, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 23, 39))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 23, 39))
never;
type X3_T1 = X3<() => "a">; // ["string", "a"]
>X3_T1 : Symbol(X3_T1, Decl(inferTypesWithExtends1.ts, 24, 10))
>X3 : Symbol(X3, Decl(inferTypesWithExtends1.ts, 18, 37))
type X3_T2 = X3<() => 1>; // ["number", 1]
>X3_T2 : Symbol(X3_T2, Decl(inferTypesWithExtends1.ts, 26, 27))
>X3 : Symbol(X3, Decl(inferTypesWithExtends1.ts, 18, 37))
type X3_T3 = X3<() => object>; // never
>X3_T3 : Symbol(X3_T3, Decl(inferTypesWithExtends1.ts, 27, 25))
>X3 : Symbol(X3, Decl(inferTypesWithExtends1.ts, 18, 37))
// infer to instance type
type X4<T extends new (...args: any[]) => any> =
>X4 : Symbol(X4, Decl(inferTypesWithExtends1.ts, 28, 30))
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 31, 8))
>args : Symbol(args, Decl(inferTypesWithExtends1.ts, 31, 23))
T extends new (...args: any[]) => infer U extends { a: string } ? ["string", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 31, 8))
>args : Symbol(args, Decl(inferTypesWithExtends1.ts, 32, 19))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 32, 43))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 32, 55))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 32, 43))
T extends new (...args: any[]) => infer U extends { a: number } ? ["number", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 31, 8))
>args : Symbol(args, Decl(inferTypesWithExtends1.ts, 33, 19))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 33, 43))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 33, 55))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 33, 43))
never;
type X4_T1 = X4<new () => { a: "a" }>; // ["string", { a: "a" }]
>X4_T1 : Symbol(X4_T1, Decl(inferTypesWithExtends1.ts, 34, 10))
>X4 : Symbol(X4, Decl(inferTypesWithExtends1.ts, 28, 30))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 36, 27))
type X4_T2 = X4<new () => { a: 1 }>; // ["number", { a: 1 }]
>X4_T2 : Symbol(X4_T2, Decl(inferTypesWithExtends1.ts, 36, 38))
>X4 : Symbol(X4, Decl(inferTypesWithExtends1.ts, 28, 30))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 37, 27))
type X4_T3 = X4<new () => { a: object }>; // never
>X4_T3 : Symbol(X4_T3, Decl(inferTypesWithExtends1.ts, 37, 36))
>X4 : Symbol(X4, Decl(inferTypesWithExtends1.ts, 28, 30))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 38, 27))
// infer to type argument
type X5<T> =
>X5 : Symbol(X5, Decl(inferTypesWithExtends1.ts, 38, 41))
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 41, 8))
T extends Promise<infer U extends string> ? ["string", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 41, 8))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 42, 27))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 42, 27))
T extends Promise<infer U extends number> ? ["number", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 41, 8))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 43, 27))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 43, 27))
never;
type X5_T1 = X5<Promise<"a" | "b">>; // ["string", "a" | "b"]
>X5_T1 : Symbol(X5_T1, Decl(inferTypesWithExtends1.ts, 44, 10))
>X5 : Symbol(X5, Decl(inferTypesWithExtends1.ts, 38, 41))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --))
type X5_T2 = X5<Promise<1 | 2>>; // ["number", 1 | 2]
>X5_T2 : Symbol(X5_T2, Decl(inferTypesWithExtends1.ts, 46, 36))
>X5 : Symbol(X5, Decl(inferTypesWithExtends1.ts, 38, 41))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --))
type X5_T3 = X5<Promise<1n | 2n>>; // never
>X5_T3 : Symbol(X5_T3, Decl(inferTypesWithExtends1.ts, 47, 32))
>X5 : Symbol(X5, Decl(inferTypesWithExtends1.ts, 38, 41))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --))
// infer to property type
type X6<T> =
>X6 : Symbol(X6, Decl(inferTypesWithExtends1.ts, 48, 34))
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 51, 8))
T extends { a: infer U extends string } ? ["string", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 51, 8))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 52, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 52, 24))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 52, 24))
T extends { a: infer U extends number } ? ["number", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 51, 8))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 53, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 53, 24))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 53, 24))
never;
type X6_T1 = X6<{ a: "a" }>; // ["string", "a"]
>X6_T1 : Symbol(X6_T1, Decl(inferTypesWithExtends1.ts, 54, 10))
>X6 : Symbol(X6, Decl(inferTypesWithExtends1.ts, 48, 34))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 56, 17))
type X6_T2 = X6<{ a: 1 }>; // ["number", 1]
>X6_T2 : Symbol(X6_T2, Decl(inferTypesWithExtends1.ts, 56, 28))
>X6 : Symbol(X6, Decl(inferTypesWithExtends1.ts, 48, 34))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 57, 17))
type X6_T3 = X6<{ a: object }>; // never
>X6_T3 : Symbol(X6_T3, Decl(inferTypesWithExtends1.ts, 57, 26))
>X6 : Symbol(X6, Decl(inferTypesWithExtends1.ts, 48, 34))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 58, 17))
// infer twice with same constraint
type X7<T> =
>X7 : Symbol(X7, Decl(inferTypesWithExtends1.ts, 58, 31))
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 61, 8))
T extends { a: infer U extends string, b: infer U extends string } ? ["string", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 61, 8))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 62, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 62, 24), Decl(inferTypesWithExtends1.ts, 62, 51))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 62, 42))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 62, 24), Decl(inferTypesWithExtends1.ts, 62, 51))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 62, 24), Decl(inferTypesWithExtends1.ts, 62, 51))
T extends { a: infer U extends number, b: infer U extends number } ? ["number", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 61, 8))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 63, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 63, 24), Decl(inferTypesWithExtends1.ts, 63, 51))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 63, 42))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 63, 24), Decl(inferTypesWithExtends1.ts, 63, 51))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 63, 24), Decl(inferTypesWithExtends1.ts, 63, 51))
never;
type X7_T1 = X7<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
>X7_T1 : Symbol(X7_T1, Decl(inferTypesWithExtends1.ts, 64, 10))
>X7 : Symbol(X7, Decl(inferTypesWithExtends1.ts, 58, 31))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 66, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 66, 25))
type X7_T2 = X7<{ a: 1, b: 2 }>; // ["number", 1 | 2]
>X7_T2 : Symbol(X7_T2, Decl(inferTypesWithExtends1.ts, 66, 36))
>X7 : Symbol(X7, Decl(inferTypesWithExtends1.ts, 58, 31))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 67, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 67, 23))
type X7_T3 = X7<{ a: object, b: object }>; // never
>X7_T3 : Symbol(X7_T3, Decl(inferTypesWithExtends1.ts, 67, 32))
>X7 : Symbol(X7, Decl(inferTypesWithExtends1.ts, 58, 31))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 68, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 68, 28))
type X7_T4 = X7<{ a: "a", b: 1 }>; // never
>X7_T4 : Symbol(X7_T4, Decl(inferTypesWithExtends1.ts, 68, 42))
>X7 : Symbol(X7, Decl(inferTypesWithExtends1.ts, 58, 31))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 69, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 69, 25))
// infer twice with missing second constraint (same behavior as class/interface)
type X8<T> =
>X8 : Symbol(X8, Decl(inferTypesWithExtends1.ts, 69, 34))
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 72, 8))
T extends { a: infer U extends string, b: infer U } ? ["string", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 72, 8))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 73, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 73, 24), Decl(inferTypesWithExtends1.ts, 73, 51))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 73, 42))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 73, 24), Decl(inferTypesWithExtends1.ts, 73, 51))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 73, 24), Decl(inferTypesWithExtends1.ts, 73, 51))
T extends { a: infer U extends number, b: infer U } ? ["number", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 72, 8))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 74, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 74, 24), Decl(inferTypesWithExtends1.ts, 74, 51))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 74, 42))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 74, 24), Decl(inferTypesWithExtends1.ts, 74, 51))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 74, 24), Decl(inferTypesWithExtends1.ts, 74, 51))
never;
type X8_T1 = X8<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
>X8_T1 : Symbol(X8_T1, Decl(inferTypesWithExtends1.ts, 75, 10))
>X8 : Symbol(X8, Decl(inferTypesWithExtends1.ts, 69, 34))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 77, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 77, 25))
type X8_T2 = X8<{ a: 1, b: 2 }>; // ["number", 1 | 2]
>X8_T2 : Symbol(X8_T2, Decl(inferTypesWithExtends1.ts, 77, 36))
>X8 : Symbol(X8, Decl(inferTypesWithExtends1.ts, 69, 34))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 78, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 78, 23))
type X8_T3 = X8<{ a: object, b: object }>; // never
>X8_T3 : Symbol(X8_T3, Decl(inferTypesWithExtends1.ts, 78, 32))
>X8 : Symbol(X8, Decl(inferTypesWithExtends1.ts, 69, 34))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 79, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 79, 28))
type X8_T4 = X8<{ a: "a", b: 1 }>; // never
>X8_T4 : Symbol(X8_T4, Decl(inferTypesWithExtends1.ts, 79, 42))
>X8 : Symbol(X8, Decl(inferTypesWithExtends1.ts, 69, 34))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 80, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 80, 25))
// infer twice with missing first constraint (same behavior as class/interface)
type X9<T> =
>X9 : Symbol(X9, Decl(inferTypesWithExtends1.ts, 80, 34))
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 83, 8))
T extends { a: infer U, b: infer U extends string } ? ["string", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 83, 8))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 84, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 84, 24), Decl(inferTypesWithExtends1.ts, 84, 36))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 84, 27))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 84, 24), Decl(inferTypesWithExtends1.ts, 84, 36))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 84, 24), Decl(inferTypesWithExtends1.ts, 84, 36))
T extends { a: infer U, b: infer U extends number } ? ["number", U] :
>T : Symbol(T, Decl(inferTypesWithExtends1.ts, 83, 8))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 85, 15))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 85, 24), Decl(inferTypesWithExtends1.ts, 85, 36))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 85, 27))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 85, 24), Decl(inferTypesWithExtends1.ts, 85, 36))
>U : Symbol(U, Decl(inferTypesWithExtends1.ts, 85, 24), Decl(inferTypesWithExtends1.ts, 85, 36))
never;
type X9_T1 = X9<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
>X9_T1 : Symbol(X9_T1, Decl(inferTypesWithExtends1.ts, 86, 10))
>X9 : Symbol(X9, Decl(inferTypesWithExtends1.ts, 80, 34))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 88, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 88, 25))
type X9_T2 = X9<{ a: 1, b: 2 }>; // ["number", 1 | 2]
>X9_T2 : Symbol(X9_T2, Decl(inferTypesWithExtends1.ts, 88, 36))
>X9 : Symbol(X9, Decl(inferTypesWithExtends1.ts, 80, 34))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 89, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 89, 23))
type X9_T3 = X9<{ a: object, b: object }>; // never
>X9_T3 : Symbol(X9_T3, Decl(inferTypesWithExtends1.ts, 89, 32))
>X9 : Symbol(X9, Decl(inferTypesWithExtends1.ts, 80, 34))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 90, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 90, 28))
type X9_T4 = X9<{ a: "a", b: 1 }>; // never
>X9_T4 : Symbol(X9_T4, Decl(inferTypesWithExtends1.ts, 90, 42))
>X9 : Symbol(X9, Decl(inferTypesWithExtends1.ts, 80, 34))
>a : Symbol(a, Decl(inferTypesWithExtends1.ts, 91, 17))
>b : Symbol(b, Decl(inferTypesWithExtends1.ts, 91, 25))
@@ -0,0 +1,235 @@
=== tests/cases/conformance/types/conditional/inferTypesWithExtends1.ts ===
// infer to tuple element
type X1<T extends any[]> =
>X1 : X1<T>
T extends [infer U extends string] ? ["string", U] :
T extends [infer U extends number] ? ["number", U] :
never;
type X1_T1 = X1<["a"]>; // ["string", "a"]
>X1_T1 : ["string", "a"]
type X1_T2 = X1<[1]>; // ["number", 1]
>X1_T2 : ["number", 1]
type X1_T3 = X1<[object]>; // never
>X1_T3 : never
// infer to argument
type X2<T extends (...args: any[]) => void> =
>X2 : X2<T>
>args : any[]
T extends (a: infer U extends string) => void ? ["string", U] :
>a : U
T extends (a: infer U extends number) => void ? ["number", U] :
>a : U
never;
type X2_T1 = X2<(a: "a") => void>; // ["string", "a"]
>X2_T1 : ["string", "a"]
>a : "a"
type X2_T2 = X2<(a: 1) => void>; // ["number", 1]
>X2_T2 : ["number", 1]
>a : 1
type X2_T3 = X2<(a: object) => void>; // never
>X2_T3 : never
>a : object
// infer to return type
type X3<T extends (...args: any[]) => any> =
>X3 : X3<T>
>args : any[]
T extends (...args: any[]) => infer U extends string ? ["string", U] :
>args : any[]
T extends (...args: any[]) => infer U extends number ? ["number", U] :
>args : any[]
never;
type X3_T1 = X3<() => "a">; // ["string", "a"]
>X3_T1 : ["string", "a"]
type X3_T2 = X3<() => 1>; // ["number", 1]
>X3_T2 : ["number", 1]
type X3_T3 = X3<() => object>; // never
>X3_T3 : never
// infer to instance type
type X4<T extends new (...args: any[]) => any> =
>X4 : X4<T>
>args : any[]
T extends new (...args: any[]) => infer U extends { a: string } ? ["string", U] :
>args : any[]
>a : string
T extends new (...args: any[]) => infer U extends { a: number } ? ["number", U] :
>args : any[]
>a : number
never;
type X4_T1 = X4<new () => { a: "a" }>; // ["string", { a: "a" }]
>X4_T1 : ["string", { a: "a"; }]
>a : "a"
type X4_T2 = X4<new () => { a: 1 }>; // ["number", { a: 1 }]
>X4_T2 : ["number", { a: 1; }]
>a : 1
type X4_T3 = X4<new () => { a: object }>; // never
>X4_T3 : never
>a : object
// infer to type argument
type X5<T> =
>X5 : X5<T>
T extends Promise<infer U extends string> ? ["string", U] :
T extends Promise<infer U extends number> ? ["number", U] :
never;
type X5_T1 = X5<Promise<"a" | "b">>; // ["string", "a" | "b"]
>X5_T1 : ["string", "a" | "b"]
type X5_T2 = X5<Promise<1 | 2>>; // ["number", 1 | 2]
>X5_T2 : ["number", 1 | 2]
type X5_T3 = X5<Promise<1n | 2n>>; // never
>X5_T3 : never
// infer to property type
type X6<T> =
>X6 : X6<T>
T extends { a: infer U extends string } ? ["string", U] :
>a : U
T extends { a: infer U extends number } ? ["number", U] :
>a : U
never;
type X6_T1 = X6<{ a: "a" }>; // ["string", "a"]
>X6_T1 : ["string", "a"]
>a : "a"
type X6_T2 = X6<{ a: 1 }>; // ["number", 1]
>X6_T2 : ["number", 1]
>a : 1
type X6_T3 = X6<{ a: object }>; // never
>X6_T3 : never
>a : object
// infer twice with same constraint
type X7<T> =
>X7 : X7<T>
T extends { a: infer U extends string, b: infer U extends string } ? ["string", U] :
>a : U
>b : U
T extends { a: infer U extends number, b: infer U extends number } ? ["number", U] :
>a : U
>b : U
never;
type X7_T1 = X7<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
>X7_T1 : ["string", "a" | "b"]
>a : "a"
>b : "b"
type X7_T2 = X7<{ a: 1, b: 2 }>; // ["number", 1 | 2]
>X7_T2 : ["number", 1 | 2]
>a : 1
>b : 2
type X7_T3 = X7<{ a: object, b: object }>; // never
>X7_T3 : never
>a : object
>b : object
type X7_T4 = X7<{ a: "a", b: 1 }>; // never
>X7_T4 : never
>a : "a"
>b : 1
// infer twice with missing second constraint (same behavior as class/interface)
type X8<T> =
>X8 : X8<T>
T extends { a: infer U extends string, b: infer U } ? ["string", U] :
>a : U
>b : U
T extends { a: infer U extends number, b: infer U } ? ["number", U] :
>a : U
>b : U
never;
type X8_T1 = X8<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
>X8_T1 : ["string", "a" | "b"]
>a : "a"
>b : "b"
type X8_T2 = X8<{ a: 1, b: 2 }>; // ["number", 1 | 2]
>X8_T2 : ["number", 1 | 2]
>a : 1
>b : 2
type X8_T3 = X8<{ a: object, b: object }>; // never
>X8_T3 : never
>a : object
>b : object
type X8_T4 = X8<{ a: "a", b: 1 }>; // never
>X8_T4 : never
>a : "a"
>b : 1
// infer twice with missing first constraint (same behavior as class/interface)
type X9<T> =
>X9 : X9<T>
T extends { a: infer U, b: infer U extends string } ? ["string", U] :
>a : U
>b : U
T extends { a: infer U, b: infer U extends number } ? ["number", U] :
>a : U
>b : U
never;
type X9_T1 = X9<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
>X9_T1 : ["string", "a" | "b"]
>a : "a"
>b : "b"
type X9_T2 = X9<{ a: 1, b: 2 }>; // ["number", 1 | 2]
>X9_T2 : ["number", 1 | 2]
>a : 1
>b : 2
type X9_T3 = X9<{ a: object, b: object }>; // never
>X9_T3 : never
>a : object
>b : object
type X9_T4 = X9<{ a: "a", b: 1 }>; // never
>X9_T4 : never
>a : "a"
>b : 1
@@ -0,0 +1,14 @@
tests/cases/conformance/types/conditional/inferTypesWithExtends2.ts(3,26): error TS2838: All declarations of 'U' must have identical constraints.
tests/cases/conformance/types/conditional/inferTypesWithExtends2.ts(3,53): error TS2838: All declarations of 'U' must have identical constraints.
==== tests/cases/conformance/types/conditional/inferTypesWithExtends2.ts (2 errors) ====
// infer twice with different constraints (same behavior as class/interface)
type X10<T> =
T extends { a: infer U extends string, b: infer U extends number } ? U :
~
!!! error TS2838: All declarations of 'U' must have identical constraints.
~
!!! error TS2838: All declarations of 'U' must have identical constraints.
never;
@@ -0,0 +1,9 @@
//// [inferTypesWithExtends2.ts]
// infer twice with different constraints (same behavior as class/interface)
type X10<T> =
T extends { a: infer U extends string, b: infer U extends number } ? U :
never;
//// [inferTypesWithExtends2.js]
"use strict";
@@ -0,0 +1,16 @@
=== tests/cases/conformance/types/conditional/inferTypesWithExtends2.ts ===
// infer twice with different constraints (same behavior as class/interface)
type X10<T> =
>X10 : Symbol(X10, Decl(inferTypesWithExtends2.ts, 0, 0))
>T : Symbol(T, Decl(inferTypesWithExtends2.ts, 1, 9))
T extends { a: infer U extends string, b: infer U extends number } ? U :
>T : Symbol(T, Decl(inferTypesWithExtends2.ts, 1, 9))
>a : Symbol(a, Decl(inferTypesWithExtends2.ts, 2, 15))
>U : Symbol(U, Decl(inferTypesWithExtends2.ts, 2, 24), Decl(inferTypesWithExtends2.ts, 2, 51))
>b : Symbol(b, Decl(inferTypesWithExtends2.ts, 2, 42))
>U : Symbol(U, Decl(inferTypesWithExtends2.ts, 2, 24), Decl(inferTypesWithExtends2.ts, 2, 51))
>U : Symbol(U, Decl(inferTypesWithExtends2.ts, 2, 24), Decl(inferTypesWithExtends2.ts, 2, 51))
never;
@@ -0,0 +1,11 @@
=== tests/cases/conformance/types/conditional/inferTypesWithExtends2.ts ===
// infer twice with different constraints (same behavior as class/interface)
type X10<T> =
>X10 : X10<T>
T extends { a: infer U extends string, b: infer U extends number } ? U :
>a : U
>b : U
never;
@@ -83,9 +83,9 @@ type T53 = X3<{ a: (x: number) => void, b: (x: string) => void }>; // never
type T54 = X3<{ a: (x: number) => void, b: () => void }>; // number
type T60 = infer U; // Error
type T61<T> = infer A extends infer B ? infer C : infer D; // Error
type T61<T> = (infer A) extends infer B ? infer C : infer D; // Error
type T62<T> = U extends (infer U)[] ? U : U; // Error
type T63<T> = T extends (infer A extends infer B ? infer C : infer D) ? string : number;
type T63<T> = T extends ((infer A) extends infer B ? infer C : infer D) ? string : number;
type T70<T extends string> = { x: T };
type T71<T> = T extends T70<infer U> ? T70<U> : never;
@@ -0,0 +1,95 @@
// @strict: true
// @declaration: true
// infer to tuple element
type X1<T extends any[]> =
T extends [infer U extends string] ? ["string", U] :
T extends [infer U extends number] ? ["number", U] :
never;
type X1_T1 = X1<["a"]>; // ["string", "a"]
type X1_T2 = X1<[1]>; // ["number", 1]
type X1_T3 = X1<[object]>; // never
// infer to argument
type X2<T extends (...args: any[]) => void> =
T extends (a: infer U extends string) => void ? ["string", U] :
T extends (a: infer U extends number) => void ? ["number", U] :
never;
type X2_T1 = X2<(a: "a") => void>; // ["string", "a"]
type X2_T2 = X2<(a: 1) => void>; // ["number", 1]
type X2_T3 = X2<(a: object) => void>; // never
// infer to return type
type X3<T extends (...args: any[]) => any> =
T extends (...args: any[]) => infer U extends string ? ["string", U] :
T extends (...args: any[]) => infer U extends number ? ["number", U] :
never;
type X3_T1 = X3<() => "a">; // ["string", "a"]
type X3_T2 = X3<() => 1>; // ["number", 1]
type X3_T3 = X3<() => object>; // never
// infer to instance type
type X4<T extends new (...args: any[]) => any> =
T extends new (...args: any[]) => infer U extends { a: string } ? ["string", U] :
T extends new (...args: any[]) => infer U extends { a: number } ? ["number", U] :
never;
type X4_T1 = X4<new () => { a: "a" }>; // ["string", { a: "a" }]
type X4_T2 = X4<new () => { a: 1 }>; // ["number", { a: 1 }]
type X4_T3 = X4<new () => { a: object }>; // never
// infer to type argument
type X5<T> =
T extends Promise<infer U extends string> ? ["string", U] :
T extends Promise<infer U extends number> ? ["number", U] :
never;
type X5_T1 = X5<Promise<"a" | "b">>; // ["string", "a" | "b"]
type X5_T2 = X5<Promise<1 | 2>>; // ["number", 1 | 2]
type X5_T3 = X5<Promise<1n | 2n>>; // never
// infer to property type
type X6<T> =
T extends { a: infer U extends string } ? ["string", U] :
T extends { a: infer U extends number } ? ["number", U] :
never;
type X6_T1 = X6<{ a: "a" }>; // ["string", "a"]
type X6_T2 = X6<{ a: 1 }>; // ["number", 1]
type X6_T3 = X6<{ a: object }>; // never
// infer twice with same constraint
type X7<T> =
T extends { a: infer U extends string, b: infer U extends string } ? ["string", U] :
T extends { a: infer U extends number, b: infer U extends number } ? ["number", U] :
never;
type X7_T1 = X7<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
type X7_T2 = X7<{ a: 1, b: 2 }>; // ["number", 1 | 2]
type X7_T3 = X7<{ a: object, b: object }>; // never
type X7_T4 = X7<{ a: "a", b: 1 }>; // never
// infer twice with missing second constraint (same behavior as class/interface)
type X8<T> =
T extends { a: infer U extends string, b: infer U } ? ["string", U] :
T extends { a: infer U extends number, b: infer U } ? ["number", U] :
never;
type X8_T1 = X8<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
type X8_T2 = X8<{ a: 1, b: 2 }>; // ["number", 1 | 2]
type X8_T3 = X8<{ a: object, b: object }>; // never
type X8_T4 = X8<{ a: "a", b: 1 }>; // never
// infer twice with missing first constraint (same behavior as class/interface)
type X9<T> =
T extends { a: infer U, b: infer U extends string } ? ["string", U] :
T extends { a: infer U, b: infer U extends number } ? ["number", U] :
never;
type X9_T1 = X9<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
type X9_T2 = X9<{ a: 1, b: 2 }>; // ["number", 1 | 2]
type X9_T3 = X9<{ a: object, b: object }>; // never
type X9_T4 = X9<{ a: "a", b: 1 }>; // never
@@ -0,0 +1,6 @@
// @strict: true
// infer twice with different constraints (same behavior as class/interface)
type X10<T> =
T extends { a: infer U extends string, b: infer U extends number } ? U :
never;
@@ -1,13 +1,13 @@
/// <reference path='fourslash.ts' />
//// type Crazy<T> = /*a*/T extends [infer P, (infer R extends string ? string : never)] ? P & R : string/*b*/;
//// type Crazy<T> = /*a*/T extends [infer P, ((infer R) extends string ? string : never)] ? P & R : string/*b*/;
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Extract type",
actionName: "Extract to type alias",
actionDescription: "Extract to type alias",
newContent: `type /*RENAME*/NewType<T> = T extends [infer P, (infer R extends string ? string : never)] ? P & R : string;
newContent: `type /*RENAME*/NewType<T> = T extends [infer P, ((infer R) extends string ? string : never)] ? P & R : string;
type Crazy<T> = NewType<T>;`,
});