mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add 'extends' clause to 'infer' type
This commit is contained in:
+19
-3
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>;`,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user