diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c5701087ebfd4..f8a6a752a6f1e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26784,13 +26784,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (candidate === blockedStringType) { return; } - if (inference.priority === undefined || priority < inference.priority) { + const combinedPriority = priority | (inference.individualPriority || InferencePriority.None); + if (inference.priority === undefined || priority < (inference.priority & ~InferencePriority.DistributiveConditional)) { inference.candidates = undefined; inference.contraCandidates = undefined; inference.topLevel = true; - inference.priority = priority; + inference.priority = combinedPriority; } - if (priority === inference.priority) { + if (priority === (inference.priority & ~InferencePriority.DistributiveConditional)) { + if (inference.priority !== combinedPriority) { + inference.priority = combinedPriority; + clearCachedInferences(inferences); + } // We make contravariant inferences only if we are in a pure contravariant position, // i.e. only if we have not descended into a bivariant position. if (contravariant && !bivariant) { @@ -27156,6 +27161,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function inferToConditionalType(source: Type, target: ConditionalType) { + const info = target.root.isDistributive ? getInferenceInfoForType(getActualTypeVariable(target.checkType)) : undefined; + const saveIndividualPriority = info?.individualPriority; + if (info) { + info.individualPriority = (info.individualPriority || InferencePriority.None) | InferencePriority.DistributiveConditional; + } if (source.flags & TypeFlags.Conditional) { inferFromTypes((source as ConditionalType).checkType, target.checkType); inferFromTypes((source as ConditionalType).extendsType, target.extendsType); @@ -27166,6 +27176,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetTypes = [getTrueTypeFromConditionalType(target), getFalseTypeFromConditionalType(target)]; inferToMultipleTypesWithPriority(source, targetTypes, target.flags, contravariant ? InferencePriority.ContravariantConditional : 0); } + if (info) { + info.individualPriority = saveIndividualPriority; + } } function inferToTemplateLiteralType(source: Type, target: TemplateLiteralType) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1cfe3e04ba68d..5b0607f38b7be 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -7102,11 +7102,12 @@ export const enum InferencePriority { ContravariantConditional = 1 << 6, // Conditional type in contravariant position ReturnType = 1 << 7, // Inference made from return type of generic function LiteralKeyof = 1 << 8, // Inference made from a string literal to a keyof T - NoConstraints = 1 << 9, // Don't infer from constraints of instantiable types - AlwaysStrict = 1 << 10, // Always use strict rules for contravariant inferences - MaxValue = 1 << 11, // Seed for inference priority tracking + DistributiveConditional = 1 << 9, + NoConstraints = 1 << 10, // Don't infer from constraints of instantiable types + AlwaysStrict = 1 << 11, // Always use strict rules for contravariant inferences + MaxValue = 1 << 12, // Seed for inference priority tracking - PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof, // These priorities imply that the resulting type should be a combination of all candidates + PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof | DistributiveConditional, // These priorities imply that the resulting type should be a combination of all candidates Circularity = -1, // Inference circularity (value less than all other priorities) } @@ -7118,6 +7119,7 @@ export interface InferenceInfo { contraCandidates: Type[] | undefined; // Candidates in contravariant positions (or undefined) inferredType?: Type; // Cache for resolved inferred type priority?: InferencePriority; // Priority of current inference set + individualPriority?: InferencePriority; topLevel: boolean; // True if all inferences are to top level occurrences isFixed: boolean; // True if inferences are fixed impliedArity?: number; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 87942520f2ab0..752b0f6725da3 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -6893,10 +6893,11 @@ declare namespace ts { ContravariantConditional = 64, ReturnType = 128, LiteralKeyof = 256, - NoConstraints = 512, - AlwaysStrict = 1024, - MaxValue = 2048, - PriorityImpliesCombination = 416, + DistributiveConditional = 512, + NoConstraints = 1024, + AlwaysStrict = 2048, + MaxValue = 4096, + PriorityImpliesCombination = 928, Circularity = -1, } interface FileExtensionInfo { diff --git a/tests/baselines/reference/genericFunctionParametersConditionalType1.symbols b/tests/baselines/reference/genericFunctionParametersConditionalType1.symbols new file mode 100644 index 0000000000000..f89e37c677e74 --- /dev/null +++ b/tests/baselines/reference/genericFunctionParametersConditionalType1.symbols @@ -0,0 +1,145 @@ +//// [tests/cases/compiler/genericFunctionParametersConditionalType1.ts] //// + +=== genericFunctionParametersConditionalType1.ts === +// https://github.com/microsoft/TypeScript/issues/62079 + +export {}; + +interface _Map { +>_Map : Symbol(_Map, Decl(genericFunctionParametersConditionalType1.ts, 2, 10)) + + foo: { a: 123 } +>foo : Symbol(_Map.foo, Decl(genericFunctionParametersConditionalType1.ts, 4, 16)) +>a : Symbol(a, Decl(genericFunctionParametersConditionalType1.ts, 5, 8)) +} + +type ModuleSubType = "bar" & { brand: true }; +>ModuleSubType : Symbol(ModuleSubType, Decl(genericFunctionParametersConditionalType1.ts, 6, 1)) +>brand : Symbol(brand, Decl(genericFunctionParametersConditionalType1.ts, 8, 30)) + +type Map = _Map & Record +>Map : Symbol(Map, Decl(genericFunctionParametersConditionalType1.ts, 8, 45)) +>_Map : Symbol(_Map, Decl(genericFunctionParametersConditionalType1.ts, 2, 10)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>ModuleSubType : Symbol(ModuleSubType, Decl(genericFunctionParametersConditionalType1.ts, 6, 1)) +>blah : Symbol(blah, Decl(genericFunctionParametersConditionalType1.ts, 10, 41)) + +type SubTypeGet< +>SubTypeGet : Symbol(SubTypeGet, Decl(genericFunctionParametersConditionalType1.ts, 10, 57)) + + SubType extends string, +>SubType : Symbol(SubType, Decl(genericFunctionParametersConditionalType1.ts, 12, 16)) + + Map extends Record, +>Map : Symbol(Map, Decl(genericFunctionParametersConditionalType1.ts, 13, 25)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>SubType : Symbol(SubType, Decl(genericFunctionParametersConditionalType1.ts, 12, 16)) + +> = SubType extends unknown +>SubType : Symbol(SubType, Decl(genericFunctionParametersConditionalType1.ts, 12, 16)) + +? { type?: SubType } & Map[SubType] +>type : Symbol(type, Decl(genericFunctionParametersConditionalType1.ts, 16, 3)) +>SubType : Symbol(SubType, Decl(genericFunctionParametersConditionalType1.ts, 12, 16)) +>Map : Symbol(Map, Decl(genericFunctionParametersConditionalType1.ts, 13, 25)) +>SubType : Symbol(SubType, Decl(genericFunctionParametersConditionalType1.ts, 12, 16)) + +: never; + +type TestParameters = Parameters<(arg: SubTypeGet) => void> +>TestParameters : Symbol(TestParameters, Decl(genericFunctionParametersConditionalType1.ts, 17, 8)) +>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 19, 34)) +>ModuleSubType : Symbol(ModuleSubType, Decl(genericFunctionParametersConditionalType1.ts, 6, 1)) +>arg : Symbol(arg, Decl(genericFunctionParametersConditionalType1.ts, 19, 67)) +>SubTypeGet : Symbol(SubTypeGet, Decl(genericFunctionParametersConditionalType1.ts, 10, 57)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 19, 34)) +>Map : Symbol(Map, Decl(genericFunctionParametersConditionalType1.ts, 8, 45)) + +declare class Test { +>Test : Symbol(Test, Decl(genericFunctionParametersConditionalType1.ts, 19, 100)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 21, 19)) +>ModuleSubType : Symbol(ModuleSubType, Decl(genericFunctionParametersConditionalType1.ts, 6, 1)) + + constructor(arg: SubTypeGet); +>arg : Symbol(arg, Decl(genericFunctionParametersConditionalType1.ts, 22, 14)) +>SubTypeGet : Symbol(SubTypeGet, Decl(genericFunctionParametersConditionalType1.ts, 10, 57)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 21, 19)) +>Map : Symbol(Map, Decl(genericFunctionParametersConditionalType1.ts, 8, 45)) +} + +type TestConstructorParameters = ConstructorParameters; +>TestConstructorParameters : Symbol(TestConstructorParameters, Decl(genericFunctionParametersConditionalType1.ts, 23, 1)) +>ConstructorParameters : Symbol(ConstructorParameters, Decl(lib.es5.d.ts, --, --)) +>Test : Symbol(Test, Decl(genericFunctionParametersConditionalType1.ts, 19, 100)) + +declare class Animal { eat(): void; } +>Animal : Symbol(Animal, Decl(genericFunctionParametersConditionalType1.ts, 25, 68)) +>eat : Symbol(Animal.eat, Decl(genericFunctionParametersConditionalType1.ts, 27, 22)) + +declare class Cat extends Animal { meow(): void; } +>Cat : Symbol(Cat, Decl(genericFunctionParametersConditionalType1.ts, 27, 37)) +>Animal : Symbol(Animal, Decl(genericFunctionParametersConditionalType1.ts, 25, 68)) +>meow : Symbol(Cat.meow, Decl(genericFunctionParametersConditionalType1.ts, 28, 34)) + +declare class Dog extends Animal { bark(): void; } +>Dog : Symbol(Dog, Decl(genericFunctionParametersConditionalType1.ts, 28, 50)) +>Animal : Symbol(Animal, Decl(genericFunctionParametersConditionalType1.ts, 25, 68)) +>bark : Symbol(Dog.bark, Decl(genericFunctionParametersConditionalType1.ts, 29, 34)) + +type WithDistributiveConditionalDirectlyInParam = ( +>WithDistributiveConditionalDirectlyInParam : Symbol(WithDistributiveConditionalDirectlyInParam, Decl(genericFunctionParametersConditionalType1.ts, 29, 50)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 31, 51)) +>Cat : Symbol(Cat, Decl(genericFunctionParametersConditionalType1.ts, 27, 37)) +>Dog : Symbol(Dog, Decl(genericFunctionParametersConditionalType1.ts, 28, 50)) + + arg: T extends unknown ? T : never, +>arg : Symbol(arg, Decl(genericFunctionParametersConditionalType1.ts, 31, 72)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 31, 51)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 31, 51)) + +) => void; + +type Result1 = Parameters; +>Result1 : Symbol(Result1, Decl(genericFunctionParametersConditionalType1.ts, 33, 10)) +>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --)) +>WithDistributiveConditionalDirectlyInParam : Symbol(WithDistributiveConditionalDirectlyInParam, Decl(genericFunctionParametersConditionalType1.ts, 29, 50)) + +type WithDistributiveConditionalNested = ( +>WithDistributiveConditionalNested : Symbol(WithDistributiveConditionalNested, Decl(genericFunctionParametersConditionalType1.ts, 35, 70)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 37, 42)) +>Cat : Symbol(Cat, Decl(genericFunctionParametersConditionalType1.ts, 27, 37)) +>Dog : Symbol(Dog, Decl(genericFunctionParametersConditionalType1.ts, 28, 50)) + + arg: T extends unknown ? { animal: T } : never, +>arg : Symbol(arg, Decl(genericFunctionParametersConditionalType1.ts, 37, 63)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 37, 42)) +>animal : Symbol(animal, Decl(genericFunctionParametersConditionalType1.ts, 38, 28)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 37, 42)) + +) => void; + +type Result2 = Parameters; +>Result2 : Symbol(Result2, Decl(genericFunctionParametersConditionalType1.ts, 39, 10)) +>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --)) +>WithDistributiveConditionalNested : Symbol(WithDistributiveConditionalNested, Decl(genericFunctionParametersConditionalType1.ts, 35, 70)) + +type WithNonDistributiveConditionalNested = ( +>WithNonDistributiveConditionalNested : Symbol(WithNonDistributiveConditionalNested, Decl(genericFunctionParametersConditionalType1.ts, 41, 61)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 43, 45)) +>Cat : Symbol(Cat, Decl(genericFunctionParametersConditionalType1.ts, 27, 37)) +>Dog : Symbol(Dog, Decl(genericFunctionParametersConditionalType1.ts, 28, 50)) + + arg: [T] extends [unknown] ? { animal: T } : never, +>arg : Symbol(arg, Decl(genericFunctionParametersConditionalType1.ts, 43, 66)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 43, 45)) +>animal : Symbol(animal, Decl(genericFunctionParametersConditionalType1.ts, 44, 32)) +>T : Symbol(T, Decl(genericFunctionParametersConditionalType1.ts, 43, 45)) + +) => void; + +type Result3 = Parameters; +>Result3 : Symbol(Result3, Decl(genericFunctionParametersConditionalType1.ts, 45, 10)) +>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --)) +>WithNonDistributiveConditionalNested : Symbol(WithNonDistributiveConditionalNested, Decl(genericFunctionParametersConditionalType1.ts, 41, 61)) + diff --git a/tests/baselines/reference/genericFunctionParametersConditionalType1.types b/tests/baselines/reference/genericFunctionParametersConditionalType1.types new file mode 100644 index 0000000000000..35467c015c815 --- /dev/null +++ b/tests/baselines/reference/genericFunctionParametersConditionalType1.types @@ -0,0 +1,131 @@ +//// [tests/cases/compiler/genericFunctionParametersConditionalType1.ts] //// + +=== genericFunctionParametersConditionalType1.ts === +// https://github.com/microsoft/TypeScript/issues/62079 + +export {}; + +interface _Map { + foo: { a: 123 } +>foo : { a: 123; } +> : ^^^^^ ^^^ +>a : 123 +> : ^^^ +} + +type ModuleSubType = "bar" & { brand: true }; +>ModuleSubType : ModuleSubType +> : ^^^^^^^^^^^^^ +>brand : true +> : ^^^^ +>true : true +> : ^^^^ + +type Map = _Map & Record +>Map : Map +> : ^^^ +>blah : string +> : ^^^^^^ + +type SubTypeGet< +>SubTypeGet : SubTypeGet +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + SubType extends string, + Map extends Record, +> = SubType extends unknown +? { type?: SubType } & Map[SubType] +>type : SubType | undefined +> : ^^^^^^^^^^^^^^^^^^^ + +: never; + +type TestParameters = Parameters<(arg: SubTypeGet) => void> +>TestParameters : [arg: { type?: ModuleSubType | undefined; } | ({ type?: "foo" | undefined; } & { a: 123; })] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ +>arg : SubTypeGet +> : ^^^^^^^^^^^^^^^^^^ + +declare class Test { +>Test : Test +> : ^^^^^^^ + + constructor(arg: SubTypeGet); +>arg : SubTypeGet +> : ^^^^^^^^^^^^^^^^^^ +} + +type TestConstructorParameters = ConstructorParameters; +>TestConstructorParameters : [arg: { type?: ModuleSubType | undefined; } | ({ type?: "foo" | undefined; } & { a: 123; })] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ +>Test : typeof Test +> : ^^^^^^^^^^^ + +declare class Animal { eat(): void; } +>Animal : Animal +> : ^^^^^^ +>eat : () => void +> : ^^^^^^ + +declare class Cat extends Animal { meow(): void; } +>Cat : Cat +> : ^^^ +>Animal : Animal +> : ^^^^^^ +>meow : () => void +> : ^^^^^^ + +declare class Dog extends Animal { bark(): void; } +>Dog : Dog +> : ^^^ +>Animal : Animal +> : ^^^^^^ +>bark : () => void +> : ^^^^^^ + +type WithDistributiveConditionalDirectlyInParam = ( +>WithDistributiveConditionalDirectlyInParam : WithDistributiveConditionalDirectlyInParam +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + arg: T extends unknown ? T : never, +>arg : T extends unknown ? T : never +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +) => void; + +type Result1 = Parameters; +>Result1 : [arg: Cat | Dog] +> : ^^^^^^^^^^^^^^^^ + +type WithDistributiveConditionalNested = ( +>WithDistributiveConditionalNested : WithDistributiveConditionalNested +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + arg: T extends unknown ? { animal: T } : never, +>arg : T extends unknown ? { animal: T; } : never +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^ +>animal : T +> : ^ + +) => void; + +type Result2 = Parameters; +>Result2 : [arg: { animal: Cat; } | { animal: Dog; }] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +type WithNonDistributiveConditionalNested = ( +>WithNonDistributiveConditionalNested : WithNonDistributiveConditionalNested +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + arg: [T] extends [unknown] ? { animal: T } : never, +>arg : [T] extends [unknown] ? { animal: T; } : never +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^ +>animal : T +> : ^ + +) => void; + +type Result3 = Parameters; +>Result3 : [arg: { animal: Cat | Dog; }] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/baselines/reference/inferToDistributiveConditionalType1.symbols b/tests/baselines/reference/inferToDistributiveConditionalType1.symbols new file mode 100644 index 0000000000000..4f000ccc00536 --- /dev/null +++ b/tests/baselines/reference/inferToDistributiveConditionalType1.symbols @@ -0,0 +1,38 @@ +//// [tests/cases/compiler/inferToDistributiveConditionalType1.ts] //// + +=== inferToDistributiveConditionalType1.ts === +declare class Animal { eat(): void; } +>Animal : Symbol(Animal, Decl(inferToDistributiveConditionalType1.ts, 0, 0)) +>eat : Symbol(Animal.eat, Decl(inferToDistributiveConditionalType1.ts, 0, 22)) + +declare class Cat extends Animal { meow(): void; } +>Cat : Symbol(Cat, Decl(inferToDistributiveConditionalType1.ts, 0, 37)) +>Animal : Symbol(Animal, Decl(inferToDistributiveConditionalType1.ts, 0, 0)) +>meow : Symbol(Cat.meow, Decl(inferToDistributiveConditionalType1.ts, 1, 34)) + +declare class Dog extends Animal { bark(): void; } +>Dog : Symbol(Dog, Decl(inferToDistributiveConditionalType1.ts, 1, 50)) +>Animal : Symbol(Animal, Decl(inferToDistributiveConditionalType1.ts, 0, 0)) +>bark : Symbol(Dog.bark, Decl(inferToDistributiveConditionalType1.ts, 2, 34)) + +declare function test1(a: T extends unknown ? { prop: T } : never): T; +>test1 : Symbol(test1, Decl(inferToDistributiveConditionalType1.ts, 2, 50)) +>T : Symbol(T, Decl(inferToDistributiveConditionalType1.ts, 4, 23)) +>a : Symbol(a, Decl(inferToDistributiveConditionalType1.ts, 4, 26)) +>T : Symbol(T, Decl(inferToDistributiveConditionalType1.ts, 4, 23)) +>prop : Symbol(prop, Decl(inferToDistributiveConditionalType1.ts, 4, 50)) +>T : Symbol(T, Decl(inferToDistributiveConditionalType1.ts, 4, 23)) +>T : Symbol(T, Decl(inferToDistributiveConditionalType1.ts, 4, 23)) + +declare const arg1: { prop: Dog } | { prop: Cat }; +>arg1 : Symbol(arg1, Decl(inferToDistributiveConditionalType1.ts, 5, 13)) +>prop : Symbol(prop, Decl(inferToDistributiveConditionalType1.ts, 5, 21)) +>Dog : Symbol(Dog, Decl(inferToDistributiveConditionalType1.ts, 1, 50)) +>prop : Symbol(prop, Decl(inferToDistributiveConditionalType1.ts, 5, 37)) +>Cat : Symbol(Cat, Decl(inferToDistributiveConditionalType1.ts, 0, 37)) + +const result1 = test1(arg1); +>result1 : Symbol(result1, Decl(inferToDistributiveConditionalType1.ts, 6, 5)) +>test1 : Symbol(test1, Decl(inferToDistributiveConditionalType1.ts, 2, 50)) +>arg1 : Symbol(arg1, Decl(inferToDistributiveConditionalType1.ts, 5, 13)) + diff --git a/tests/baselines/reference/inferToDistributiveConditionalType1.types b/tests/baselines/reference/inferToDistributiveConditionalType1.types new file mode 100644 index 0000000000000..83309450eb075 --- /dev/null +++ b/tests/baselines/reference/inferToDistributiveConditionalType1.types @@ -0,0 +1,51 @@ +//// [tests/cases/compiler/inferToDistributiveConditionalType1.ts] //// + +=== inferToDistributiveConditionalType1.ts === +declare class Animal { eat(): void; } +>Animal : Animal +> : ^^^^^^ +>eat : () => void +> : ^^^^^^ + +declare class Cat extends Animal { meow(): void; } +>Cat : Cat +> : ^^^ +>Animal : Animal +> : ^^^^^^ +>meow : () => void +> : ^^^^^^ + +declare class Dog extends Animal { bark(): void; } +>Dog : Dog +> : ^^^ +>Animal : Animal +> : ^^^^^^ +>bark : () => void +> : ^^^^^^ + +declare function test1(a: T extends unknown ? { prop: T } : never): T; +>test1 : (a: T extends unknown ? { prop: T; } : never) => T +> : ^ ^^ ^^ ^^^^^ +>a : T extends unknown ? { prop: T; } : never +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^ +>prop : T +> : ^ + +declare const arg1: { prop: Dog } | { prop: Cat }; +>arg1 : { prop: Dog; } | { prop: Cat; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>prop : Dog +> : ^^^ +>prop : Cat +> : ^^^ + +const result1 = test1(arg1); +>result1 : Cat | Dog +> : ^^^^^^^^^ +>test1(arg1) : Cat | Dog +> : ^^^^^^^^^ +>test1 : (a: T extends unknown ? { prop: T; } : never) => T +> : ^ ^^ ^^ ^^^^^ +>arg1 : { prop: Dog; } | { prop: Cat; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ + diff --git a/tests/cases/compiler/genericFunctionParametersConditionalType1.ts b/tests/cases/compiler/genericFunctionParametersConditionalType1.ts new file mode 100644 index 0000000000000..7bcce5c36b83a --- /dev/null +++ b/tests/cases/compiler/genericFunctionParametersConditionalType1.ts @@ -0,0 +1,51 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/62079 + +export {}; + +interface _Map { + foo: { a: 123 } +} + +type ModuleSubType = "bar" & { brand: true }; + +type Map = _Map & Record + +type SubTypeGet< + SubType extends string, + Map extends Record, +> = SubType extends unknown +? { type?: SubType } & Map[SubType] +: never; + +type TestParameters = Parameters<(arg: SubTypeGet) => void> + +declare class Test { + constructor(arg: SubTypeGet); +} + +type TestConstructorParameters = ConstructorParameters; + +declare class Animal { eat(): void; } +declare class Cat extends Animal { meow(): void; } +declare class Dog extends Animal { bark(): void; } + +type WithDistributiveConditionalDirectlyInParam = ( + arg: T extends unknown ? T : never, +) => void; + +type Result1 = Parameters; + +type WithDistributiveConditionalNested = ( + arg: T extends unknown ? { animal: T } : never, +) => void; + +type Result2 = Parameters; + +type WithNonDistributiveConditionalNested = ( + arg: [T] extends [unknown] ? { animal: T } : never, +) => void; + +type Result3 = Parameters; diff --git a/tests/cases/compiler/inferToDistributiveConditionalType1.ts b/tests/cases/compiler/inferToDistributiveConditionalType1.ts new file mode 100644 index 0000000000000..fb93b9a0252fe --- /dev/null +++ b/tests/cases/compiler/inferToDistributiveConditionalType1.ts @@ -0,0 +1,10 @@ +// @strict: true +// @noEmit: true + +declare class Animal { eat(): void; } +declare class Cat extends Animal { meow(): void; } +declare class Dog extends Animal { bark(): void; } + +declare function test1(a: T extends unknown ? { prop: T } : never): T; +declare const arg1: { prop: Dog } | { prop: Cat }; +const result1 = test1(arg1);