diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fcb93c45dc1dd..0a8c3b4af28d6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19328,7 +19328,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeParamMapper = combineTypeMappers((newType as ConditionalType).mapper, newMapper); const typeArguments = map(newRoot.outerTypeParameters, t => getMappedType(t, typeParamMapper)); const newRootMapper = createTypeMapper(newRoot.outerTypeParameters, typeArguments); - const newCheckType = newRoot.isDistributive ? getMappedType(newRoot.checkType, newRootMapper) : undefined; + let newCheckType = newRoot.isDistributive ? getMappedType(newRoot.checkType, newRootMapper) : undefined; + if (newCheckType && isNoInferType(newCheckType)) { + newCheckType = (newCheckType as SubstitutionType).baseType; + } if (!newCheckType || newCheckType === newRoot.checkType || !(newCheckType.flags & (TypeFlags.Union | TypeFlags.Never))) { root = newRoot; mapper = newRootMapper; @@ -20422,6 +20425,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const newMapper = createTypeMapper(root.outerTypeParameters, typeArguments); const checkType = root.checkType; let distributionType = root.isDistributive ? getReducedType(getMappedType(checkType, newMapper)) : undefined; + if (distributionType && isNoInferType(distributionType)) { + distributionType = (distributionType as SubstitutionType).baseType; + } let narrowingBaseType: Type | undefined; const forNarrowing = distributionType && isNarrowingSubstitutionType(distributionType) && isNarrowableConditionalType(type, mapper); if (forNarrowing) { diff --git a/tests/baselines/reference/noInferVsDistributiveConditionalType1.symbols b/tests/baselines/reference/noInferVsDistributiveConditionalType1.symbols new file mode 100644 index 0000000000000..2d73830cc67db --- /dev/null +++ b/tests/baselines/reference/noInferVsDistributiveConditionalType1.symbols @@ -0,0 +1,128 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType1.ts] //// + +=== noInferVsDistributiveConditionalType1.ts === +// https://github.com/microsoft/TypeScript/issues/61076 + +type FooEvent = { type: "FOO" }; +>FooEvent : Symbol(FooEvent, Decl(noInferVsDistributiveConditionalType1.ts, 0, 0)) +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType1.ts, 2, 17)) + +type BarEvent = { type: "BAR" }; +>BarEvent : Symbol(BarEvent, Decl(noInferVsDistributiveConditionalType1.ts, 2, 32)) +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType1.ts, 3, 17)) + +type Input = FooEvent | BarEvent; +>Input : Symbol(Input, Decl(noInferVsDistributiveConditionalType1.ts, 3, 32)) +>FooEvent : Symbol(FooEvent, Decl(noInferVsDistributiveConditionalType1.ts, 0, 0)) +>BarEvent : Symbol(BarEvent, Decl(noInferVsDistributiveConditionalType1.ts, 2, 32)) + +type Result = Extract, FooEvent>; +>Result : Symbol(Result, Decl(noInferVsDistributiveConditionalType1.ts, 5, 33)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>Input : Symbol(Input, Decl(noInferVsDistributiveConditionalType1.ts, 3, 32)) +>FooEvent : Symbol(FooEvent, Decl(noInferVsDistributiveConditionalType1.ts, 0, 0)) + +type EventObject = { +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType1.ts, 6, 48)) + + type: string; +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType1.ts, 8, 20)) + +}; + +type ActionFunction< +>ActionFunction : Symbol(ActionFunction, Decl(noInferVsDistributiveConditionalType1.ts, 10, 2)) + + TExpressionEvent extends EventObject, +>TExpressionEvent : Symbol(TExpressionEvent, Decl(noInferVsDistributiveConditionalType1.ts, 12, 20)) +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType1.ts, 6, 48)) + + TEvent extends EventObject, +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 13, 39)) +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType1.ts, 6, 48)) + +> = { + (args: { event: TExpressionEvent }): void; +>args : Symbol(args, Decl(noInferVsDistributiveConditionalType1.ts, 16, 3)) +>event : Symbol(event, Decl(noInferVsDistributiveConditionalType1.ts, 16, 10)) +>TExpressionEvent : Symbol(TExpressionEvent, Decl(noInferVsDistributiveConditionalType1.ts, 12, 20)) + + _out_TEvent?: TEvent; +>_out_TEvent : Symbol(_out_TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 16, 44)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 13, 39)) + +}; + +type TransitionsConfig = { +>TransitionsConfig : Symbol(TransitionsConfig, Decl(noInferVsDistributiveConditionalType1.ts, 18, 2)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 20, 23)) +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType1.ts, 6, 48)) + + [K in TEvent["type"]]?: { +>K : Symbol(K, Decl(noInferVsDistributiveConditionalType1.ts, 21, 3)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 20, 23)) + + actions?: ActionFunction, TEvent>; +>actions : Symbol(actions, Decl(noInferVsDistributiveConditionalType1.ts, 21, 27)) +>ActionFunction : Symbol(ActionFunction, Decl(noInferVsDistributiveConditionalType1.ts, 10, 2)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 20, 23)) +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType1.ts, 22, 46)) +>K : Symbol(K, Decl(noInferVsDistributiveConditionalType1.ts, 21, 3)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 20, 23)) + + }; +}; + +declare function createMachine(config: { +>createMachine : Symbol(createMachine, Decl(noInferVsDistributiveConditionalType1.ts, 24, 2)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 26, 31)) +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType1.ts, 6, 48)) +>config : Symbol(config, Decl(noInferVsDistributiveConditionalType1.ts, 26, 59)) + + types?: { +>types : Symbol(types, Decl(noInferVsDistributiveConditionalType1.ts, 26, 68)) + + events?: TEvent; +>events : Symbol(events, Decl(noInferVsDistributiveConditionalType1.ts, 27, 11)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 26, 31)) + + }; + on?: TransitionsConfig>; +>on : Symbol(on, Decl(noInferVsDistributiveConditionalType1.ts, 29, 4)) +>TransitionsConfig : Symbol(TransitionsConfig, Decl(noInferVsDistributiveConditionalType1.ts, 18, 2)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 26, 31)) + +}): void; + +createMachine({ +>createMachine : Symbol(createMachine, Decl(noInferVsDistributiveConditionalType1.ts, 24, 2)) + + types: { +>types : Symbol(types, Decl(noInferVsDistributiveConditionalType1.ts, 33, 15)) + + events: {} as Input, +>events : Symbol(events, Decl(noInferVsDistributiveConditionalType1.ts, 34, 10)) +>Input : Symbol(Input, Decl(noInferVsDistributiveConditionalType1.ts, 3, 32)) + + }, + on: { +>on : Symbol(on, Decl(noInferVsDistributiveConditionalType1.ts, 36, 4)) + + FOO: { +>FOO : Symbol(FOO, Decl(noInferVsDistributiveConditionalType1.ts, 37, 7)) + + actions: ({ event }) => { +>actions : Symbol(actions, Decl(noInferVsDistributiveConditionalType1.ts, 38, 10)) +>event : Symbol(event, Decl(noInferVsDistributiveConditionalType1.ts, 39, 17)) + + event; // { type: "FOO"; } +>event : Symbol(event, Decl(noInferVsDistributiveConditionalType1.ts, 39, 17)) + + }, + }, + }, +}); + diff --git a/tests/baselines/reference/noInferVsDistributiveConditionalType1.types b/tests/baselines/reference/noInferVsDistributiveConditionalType1.types new file mode 100644 index 0000000000000..bf448a5660dfc --- /dev/null +++ b/tests/baselines/reference/noInferVsDistributiveConditionalType1.types @@ -0,0 +1,141 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType1.ts] //// + +=== noInferVsDistributiveConditionalType1.ts === +// https://github.com/microsoft/TypeScript/issues/61076 + +type FooEvent = { type: "FOO" }; +>FooEvent : FooEvent +> : ^^^^^^^^ +>type : "FOO" +> : ^^^^^ + +type BarEvent = { type: "BAR" }; +>BarEvent : BarEvent +> : ^^^^^^^^ +>type : "BAR" +> : ^^^^^ + +type Input = FooEvent | BarEvent; +>Input : Input +> : ^^^^^ + +type Result = Extract, FooEvent>; +>Result : FooEvent +> : ^^^^^^^^ + +type EventObject = { +>EventObject : EventObject +> : ^^^^^^^^^^^ + + type: string; +>type : string +> : ^^^^^^ + +}; + +type ActionFunction< +>ActionFunction : ActionFunction +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + TExpressionEvent extends EventObject, + TEvent extends EventObject, +> = { + (args: { event: TExpressionEvent }): void; +>args : { event: TExpressionEvent; } +> : ^^^^^^^^^ ^^^ +>event : TExpressionEvent +> : ^^^^^^^^^^^^^^^^ + + _out_TEvent?: TEvent; +>_out_TEvent : TEvent | undefined +> : ^^^^^^^^^^^^^^^^^^ + +}; + +type TransitionsConfig = { +>TransitionsConfig : TransitionsConfig +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in TEvent["type"]]?: { + actions?: ActionFunction, TEvent>; +>actions : ActionFunction, TEvent> | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : K +> : ^ + + }; +}; + +declare function createMachine(config: { +>createMachine : (config: { types?: { events?: TEvent; }; on?: TransitionsConfig>; }) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>config : { types?: { events?: TEvent; }; on?: TransitionsConfig>; } +> : ^^^^^^^^^^ ^^^^^^^ ^^^ + + types?: { +>types : { events?: TEvent; } | undefined +> : ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ + + events?: TEvent; +>events : TEvent | undefined +> : ^^^^^^^^^^^^^^^^^^ + + }; + on?: TransitionsConfig>; +>on : TransitionsConfig> | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +}): void; + +createMachine({ +>createMachine({ types: { events: {} as Input, }, on: { FOO: { actions: ({ event }) => { event; // { type: "FOO"; } }, }, },}) : void +> : ^^^^ +>createMachine : (config: { types?: { events?: TEvent; }; on?: TransitionsConfig>; }) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ types: { events: {} as Input, }, on: { FOO: { actions: ({ event }) => { event; // { type: "FOO"; } }, }, },} : { types: { events: Input; }; on: { FOO: { actions: ({ event }: { event: FooEvent; }) => void; }; }; } +> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + types: { +>types : { events: Input; } +> : ^^^^^^^^^^ ^^^ +>{ events: {} as Input, } : { events: Input; } +> : ^^^^^^^^^^ ^^^ + + events: {} as Input, +>events : Input +> : ^^^^^ +>{} as Input : Input +> : ^^^^^ +>{} : {} +> : ^^ + + }, + on: { +>on : { FOO: { actions: ({ event }: { event: FooEvent; }) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ FOO: { actions: ({ event }) => { event; // { type: "FOO"; } }, }, } : { FOO: { actions: ({ event }: { event: FooEvent; }) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + FOO: { +>FOO : { actions: ({ event }: { event: FooEvent; }) => void; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ actions: ({ event }) => { event; // { type: "FOO"; } }, } : { actions: ({ event }: { event: FooEvent; }) => void; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + actions: ({ event }) => { +>actions : ({ event }: { event: FooEvent; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>({ event }) => { event; // { type: "FOO"; } } : ({ event }: { event: FooEvent; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>event : FooEvent +> : ^^^^^^^^ + + event; // { type: "FOO"; } +>event : FooEvent +> : ^^^^^^^^ + + }, + }, + }, +}); + diff --git a/tests/baselines/reference/noInferVsDistributiveConditionalType2.symbols b/tests/baselines/reference/noInferVsDistributiveConditionalType2.symbols new file mode 100644 index 0000000000000..2f1b8818ef7e0 --- /dev/null +++ b/tests/baselines/reference/noInferVsDistributiveConditionalType2.symbols @@ -0,0 +1,289 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType2.ts] //// + +=== noInferVsDistributiveConditionalType2.ts === +type EventObject = { +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0)) + + type: string; +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 0, 20)) + +}; + +type FooEvent = { type: "FOO" }; +>FooEvent : Symbol(FooEvent, Decl(noInferVsDistributiveConditionalType2.ts, 2, 2)) +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 4, 17)) + +type BarEvent = { type: "BAR" }; +>BarEvent : Symbol(BarEvent, Decl(noInferVsDistributiveConditionalType2.ts, 4, 32)) +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 5, 17)) + +type Input = FooEvent | BarEvent; +>Input : Symbol(Input, Decl(noInferVsDistributiveConditionalType2.ts, 5, 32)) +>FooEvent : Symbol(FooEvent, Decl(noInferVsDistributiveConditionalType2.ts, 2, 2)) +>BarEvent : Symbol(BarEvent, Decl(noInferVsDistributiveConditionalType2.ts, 4, 32)) + +type ExtractEventSimplified< +>ExtractEventSimplified : Symbol(ExtractEventSimplified, Decl(noInferVsDistributiveConditionalType2.ts, 7, 33)) + + TEvent extends EventObject, +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 9, 28)) +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0)) + + K extends TEvent["type"], +>K : Symbol(K, Decl(noInferVsDistributiveConditionalType2.ts, 10, 29)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 9, 28)) + +> = string extends TEvent["type"] ? TEvent : Extract; +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 9, 28)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 9, 28)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 9, 28)) +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 12, 62)) +>K : Symbol(K, Decl(noInferVsDistributiveConditionalType2.ts, 10, 29)) + +type Result = ExtractEventSimplified, "FOO">; +>Result : Symbol(Result, Decl(noInferVsDistributiveConditionalType2.ts, 12, 74)) +>ExtractEventSimplified : Symbol(ExtractEventSimplified, Decl(noInferVsDistributiveConditionalType2.ts, 7, 33)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>Input : Symbol(Input, Decl(noInferVsDistributiveConditionalType2.ts, 5, 32)) + +type EventDescriptorMatches< +>EventDescriptorMatches : Symbol(EventDescriptorMatches, Decl(noInferVsDistributiveConditionalType2.ts, 14, 60)) + + TEventType extends string, +>TEventType : Symbol(TEventType, Decl(noInferVsDistributiveConditionalType2.ts, 16, 28)) + + TNormalizedDescriptor, +>TNormalizedDescriptor : Symbol(TNormalizedDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 17, 28)) + +> = TEventType extends TNormalizedDescriptor ? true : false; +>TEventType : Symbol(TEventType, Decl(noInferVsDistributiveConditionalType2.ts, 16, 28)) +>TNormalizedDescriptor : Symbol(TNormalizedDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 17, 28)) + +type PartialEventDescriptor = +>PartialEventDescriptor : Symbol(PartialEventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 19, 60)) +>TEventType : Symbol(TEventType, Decl(noInferVsDistributiveConditionalType2.ts, 21, 28)) + + TEventType extends `${infer TLeading}.${infer TTail}` +>TEventType : Symbol(TEventType, Decl(noInferVsDistributiveConditionalType2.ts, 21, 28)) +>TLeading : Symbol(TLeading, Decl(noInferVsDistributiveConditionalType2.ts, 22, 29)) +>TTail : Symbol(TTail, Decl(noInferVsDistributiveConditionalType2.ts, 22, 47)) + + ? `${TLeading}.*` | `${TLeading}.${PartialEventDescriptor}` +>TLeading : Symbol(TLeading, Decl(noInferVsDistributiveConditionalType2.ts, 22, 29)) +>TLeading : Symbol(TLeading, Decl(noInferVsDistributiveConditionalType2.ts, 22, 29)) +>PartialEventDescriptor : Symbol(PartialEventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 19, 60)) +>TTail : Symbol(TTail, Decl(noInferVsDistributiveConditionalType2.ts, 22, 47)) + + : never; + +type EventDescriptor = +>EventDescriptor : Symbol(EventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 24, 12)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 26, 21)) +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0)) + + | TEvent["type"] +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 26, 21)) + + | PartialEventDescriptor +>PartialEventDescriptor : Symbol(PartialEventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 19, 60)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 26, 21)) + + | "*"; + +type NormalizeDescriptor = TDescriptor extends "*" +>NormalizeDescriptor : Symbol(NormalizeDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 29, 8)) +>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 31, 25)) +>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 31, 25)) + + ? string + : TDescriptor extends `${infer TLeading}.*` +>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 31, 25)) +>TLeading : Symbol(TLeading, Decl(noInferVsDistributiveConditionalType2.ts, 33, 32)) + + ? `${TLeading}.${string}` +>TLeading : Symbol(TLeading, Decl(noInferVsDistributiveConditionalType2.ts, 33, 32)) + + : TDescriptor; +>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 31, 25)) + +type ExtractEvent< +>ExtractEvent : Symbol(ExtractEvent, Decl(noInferVsDistributiveConditionalType2.ts, 35, 16)) + + TEvent extends EventObject, +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18)) +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0)) + + TDescriptor extends EventDescriptor, +>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 38, 29)) +>EventDescriptor : Symbol(EventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 24, 12)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18)) + +> = string extends TEvent["type"] +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18)) + + ? TEvent +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18)) + + : NormalizeDescriptor extends infer TNormalizedDescriptor +>NormalizeDescriptor : Symbol(NormalizeDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 29, 8)) +>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 38, 29)) +>TNormalizedDescriptor : Symbol(TNormalizedDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 42, 50)) + + ? TEvent extends any +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18)) + + ? // true is the check type here to match both true and boolean + true extends EventDescriptorMatches +>EventDescriptorMatches : Symbol(EventDescriptorMatches, Decl(noInferVsDistributiveConditionalType2.ts, 14, 60)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18)) +>TNormalizedDescriptor : Symbol(TNormalizedDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 42, 50)) + + ? TEvent +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18)) + + : never + : never + : never; + +type ActionFunction< +>ActionFunction : Symbol(ActionFunction, Decl(noInferVsDistributiveConditionalType2.ts, 49, 10)) + + TExpressionEvent extends EventObject, +>TExpressionEvent : Symbol(TExpressionEvent, Decl(noInferVsDistributiveConditionalType2.ts, 51, 20)) +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0)) + + TEvent extends EventObject, +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 52, 39)) +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0)) + +> = { + (args: { event: TExpressionEvent }): void; +>args : Symbol(args, Decl(noInferVsDistributiveConditionalType2.ts, 55, 3)) +>event : Symbol(event, Decl(noInferVsDistributiveConditionalType2.ts, 55, 10)) +>TExpressionEvent : Symbol(TExpressionEvent, Decl(noInferVsDistributiveConditionalType2.ts, 51, 20)) + + _out_TEvent?: TEvent; +>_out_TEvent : Symbol(_out_TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 55, 44)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 52, 39)) + +}; + +type TransitionsConfig = { +>TransitionsConfig : Symbol(TransitionsConfig, Decl(noInferVsDistributiveConditionalType2.ts, 57, 2)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 59, 23)) +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0)) + + [K in EventDescriptor]?: { +>K : Symbol(K, Decl(noInferVsDistributiveConditionalType2.ts, 60, 3)) +>EventDescriptor : Symbol(EventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 24, 12)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 59, 23)) + + actions?: ActionFunction, TEvent>; +>actions : Symbol(actions, Decl(noInferVsDistributiveConditionalType2.ts, 60, 36)) +>ActionFunction : Symbol(ActionFunction, Decl(noInferVsDistributiveConditionalType2.ts, 49, 10)) +>ExtractEvent : Symbol(ExtractEvent, Decl(noInferVsDistributiveConditionalType2.ts, 35, 16)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 59, 23)) +>K : Symbol(K, Decl(noInferVsDistributiveConditionalType2.ts, 60, 3)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 59, 23)) + + }; +}; + +declare function createMachine(config: { +>createMachine : Symbol(createMachine, Decl(noInferVsDistributiveConditionalType2.ts, 63, 2)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 65, 31)) +>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0)) +>config : Symbol(config, Decl(noInferVsDistributiveConditionalType2.ts, 65, 59)) + + types?: { +>types : Symbol(types, Decl(noInferVsDistributiveConditionalType2.ts, 65, 68)) + + events?: TEvent; +>events : Symbol(events, Decl(noInferVsDistributiveConditionalType2.ts, 66, 11)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 65, 31)) + + }; + on?: TransitionsConfig>; +>on : Symbol(on, Decl(noInferVsDistributiveConditionalType2.ts, 68, 4)) +>TransitionsConfig : Symbol(TransitionsConfig, Decl(noInferVsDistributiveConditionalType2.ts, 57, 2)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 65, 31)) + +}): void; + +createMachine({ +>createMachine : Symbol(createMachine, Decl(noInferVsDistributiveConditionalType2.ts, 63, 2)) + + types: { +>types : Symbol(types, Decl(noInferVsDistributiveConditionalType2.ts, 72, 15)) + + events: {} as { type: "FOO" } | { type: "BAR" }, +>events : Symbol(events, Decl(noInferVsDistributiveConditionalType2.ts, 73, 10)) +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 74, 19)) +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 74, 37)) + + }, + on: { +>on : Symbol(on, Decl(noInferVsDistributiveConditionalType2.ts, 75, 4)) + + FOO: { +>FOO : Symbol(FOO, Decl(noInferVsDistributiveConditionalType2.ts, 76, 7)) + + actions: ({ event }) => { +>actions : Symbol(actions, Decl(noInferVsDistributiveConditionalType2.ts, 77, 10)) +>event : Symbol(event, Decl(noInferVsDistributiveConditionalType2.ts, 78, 17)) + + event; // { type: "FOO"; } +>event : Symbol(event, Decl(noInferVsDistributiveConditionalType2.ts, 78, 17)) + + }, + }, + }, +}); + +createMachine({ +>createMachine : Symbol(createMachine, Decl(noInferVsDistributiveConditionalType2.ts, 63, 2)) + + types: {} as { +>types : Symbol(types, Decl(noInferVsDistributiveConditionalType2.ts, 85, 15)) + + events: +>events : Symbol(events, Decl(noInferVsDistributiveConditionalType2.ts, 86, 16)) + + | { type: "mouse.click.up"; direction: "up" } +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 88, 9)) +>direction : Symbol(direction, Decl(noInferVsDistributiveConditionalType2.ts, 88, 33)) + + | { type: "mouse.click.down"; direction: "down" } +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 89, 9)) +>direction : Symbol(direction, Decl(noInferVsDistributiveConditionalType2.ts, 89, 35)) + + | { type: "mouse.move" } +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 90, 9)) + + | { type: "mouse" } +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 91, 9)) + + | { type: "keypress" }; +>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 92, 9)) + + }, + on: { +>on : Symbol(on, Decl(noInferVsDistributiveConditionalType2.ts, 93, 4)) + + "mouse.*": { +>"mouse.*" : Symbol("mouse.*", Decl(noInferVsDistributiveConditionalType2.ts, 94, 7)) + + actions: ({ event }) => { +>actions : Symbol(actions, Decl(noInferVsDistributiveConditionalType2.ts, 95, 16)) +>event : Symbol(event, Decl(noInferVsDistributiveConditionalType2.ts, 96, 17)) + + event; // { type: "mouse.click.up"; direction: "up" } | { type: "mouse.click.down"; direction: "down" } | { type: "mouse.move" } +>event : Symbol(event, Decl(noInferVsDistributiveConditionalType2.ts, 96, 17)) + + }, + }, + }, +}); + diff --git a/tests/baselines/reference/noInferVsDistributiveConditionalType2.types b/tests/baselines/reference/noInferVsDistributiveConditionalType2.types new file mode 100644 index 0000000000000..57ee7de52fba9 --- /dev/null +++ b/tests/baselines/reference/noInferVsDistributiveConditionalType2.types @@ -0,0 +1,282 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType2.ts] //// + +=== noInferVsDistributiveConditionalType2.ts === +type EventObject = { +>EventObject : EventObject +> : ^^^^^^^^^^^ + + type: string; +>type : string +> : ^^^^^^ + +}; + +type FooEvent = { type: "FOO" }; +>FooEvent : FooEvent +> : ^^^^^^^^ +>type : "FOO" +> : ^^^^^ + +type BarEvent = { type: "BAR" }; +>BarEvent : BarEvent +> : ^^^^^^^^ +>type : "BAR" +> : ^^^^^ + +type Input = FooEvent | BarEvent; +>Input : Input +> : ^^^^^ + +type ExtractEventSimplified< +>ExtractEventSimplified : ExtractEventSimplified +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + TEvent extends EventObject, + K extends TEvent["type"], +> = string extends TEvent["type"] ? TEvent : Extract; +>type : K +> : ^ + +type Result = ExtractEventSimplified, "FOO">; +>Result : FooEvent +> : ^^^^^^^^ + +type EventDescriptorMatches< +>EventDescriptorMatches : EventDescriptorMatches +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + TEventType extends string, + TNormalizedDescriptor, +> = TEventType extends TNormalizedDescriptor ? true : false; +>true : true +> : ^^^^ +>false : false +> : ^^^^^ + +type PartialEventDescriptor = +>PartialEventDescriptor : PartialEventDescriptor +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + TEventType extends `${infer TLeading}.${infer TTail}` + ? `${TLeading}.*` | `${TLeading}.${PartialEventDescriptor}` + : never; + +type EventDescriptor = +>EventDescriptor : EventDescriptor +> : ^^^^^^^^^^^^^^^^^^^^^^^ + + | TEvent["type"] + | PartialEventDescriptor + | "*"; + +type NormalizeDescriptor = TDescriptor extends "*" +>NormalizeDescriptor : NormalizeDescriptor +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ? string + : TDescriptor extends `${infer TLeading}.*` + ? `${TLeading}.${string}` + : TDescriptor; + +type ExtractEvent< +>ExtractEvent : ExtractEvent +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + TEvent extends EventObject, + TDescriptor extends EventDescriptor, +> = string extends TEvent["type"] + ? TEvent + : NormalizeDescriptor extends infer TNormalizedDescriptor + ? TEvent extends any + ? // true is the check type here to match both true and boolean + true extends EventDescriptorMatches +>true : true +> : ^^^^ + + ? TEvent + : never + : never + : never; + +type ActionFunction< +>ActionFunction : ActionFunction +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + TExpressionEvent extends EventObject, + TEvent extends EventObject, +> = { + (args: { event: TExpressionEvent }): void; +>args : { event: TExpressionEvent; } +> : ^^^^^^^^^ ^^^ +>event : TExpressionEvent +> : ^^^^^^^^^^^^^^^^ + + _out_TEvent?: TEvent; +>_out_TEvent : TEvent | undefined +> : ^^^^^^^^^^^^^^^^^^ + +}; + +type TransitionsConfig = { +>TransitionsConfig : TransitionsConfig +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ + + [K in EventDescriptor]?: { + actions?: ActionFunction, TEvent>; +>actions : ActionFunction, TEvent> | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + }; +}; + +declare function createMachine(config: { +>createMachine : (config: { types?: { events?: TEvent; }; on?: TransitionsConfig>; }) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>config : { types?: { events?: TEvent; }; on?: TransitionsConfig>; } +> : ^^^^^^^^^^ ^^^^^^^ ^^^ + + types?: { +>types : { events?: TEvent; } | undefined +> : ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ + + events?: TEvent; +>events : TEvent | undefined +> : ^^^^^^^^^^^^^^^^^^ + + }; + on?: TransitionsConfig>; +>on : TransitionsConfig> | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +}): void; + +createMachine({ +>createMachine({ types: { events: {} as { type: "FOO" } | { type: "BAR" }, }, on: { FOO: { actions: ({ event }) => { event; // { type: "FOO"; } }, }, },}) : void +> : ^^^^ +>createMachine : (config: { types?: { events?: TEvent; }; on?: TransitionsConfig>; }) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ types: { events: {} as { type: "FOO" } | { type: "BAR" }, }, on: { FOO: { actions: ({ event }) => { event; // { type: "FOO"; } }, }, },} : { types: { events: { type: "FOO"; } | { type: "BAR"; }; }; on: { FOO: { actions: ({ event }: { event: { type: "FOO"; }; }) => void; }; }; } +> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ + + types: { +>types : { events: { type: "FOO"; } | { type: "BAR"; }; } +> : ^^^^^^^^^^ ^^^ +>{ events: {} as { type: "FOO" } | { type: "BAR" }, } : { events: { type: "FOO"; } | { type: "BAR"; }; } +> : ^^^^^^^^^^ ^^^ + + events: {} as { type: "FOO" } | { type: "BAR" }, +>events : { type: "FOO"; } | { type: "BAR"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>{} as { type: "FOO" } | { type: "BAR" } : { type: "FOO"; } | { type: "BAR"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>{} : {} +> : ^^ +>type : "FOO" +> : ^^^^^ +>type : "BAR" +> : ^^^^^ + + }, + on: { +>on : { FOO: { actions: ({ event }: { event: { type: "FOO"; }; }) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ +>{ FOO: { actions: ({ event }) => { event; // { type: "FOO"; } }, }, } : { FOO: { actions: ({ event }: { event: { type: "FOO"; }; }) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ + + FOO: { +>FOO : { actions: ({ event }: { event: { type: "FOO"; }; }) => void; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ +>{ actions: ({ event }) => { event; // { type: "FOO"; } }, } : { actions: ({ event }: { event: { type: "FOO"; }; }) => void; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ + + actions: ({ event }) => { +>actions : ({ event }: { event: { type: "FOO"; }; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>({ event }) => { event; // { type: "FOO"; } } : ({ event }: { event: { type: "FOO"; }; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>event : { type: "FOO"; } +> : ^^^^^^^^ ^^^ + + event; // { type: "FOO"; } +>event : { type: "FOO"; } +> : ^^^^^^^^ ^^^ + + }, + }, + }, +}); + +createMachine({ +>createMachine({ types: {} as { events: | { type: "mouse.click.up"; direction: "up" } | { type: "mouse.click.down"; direction: "down" } | { type: "mouse.move" } | { type: "mouse" } | { type: "keypress" }; }, on: { "mouse.*": { actions: ({ event }) => { event; // { type: "mouse.click.up"; direction: "up" } | { type: "mouse.click.down"; direction: "down" } | { type: "mouse.move" } }, }, },}) : void +> : ^^^^ +>createMachine : (config: { types?: { events?: TEvent; }; on?: TransitionsConfig>; }) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ types: {} as { events: | { type: "mouse.click.up"; direction: "up" } | { type: "mouse.click.down"; direction: "down" } | { type: "mouse.move" } | { type: "mouse" } | { type: "keypress" }; }, on: { "mouse.*": { actions: ({ event }) => { event; // { type: "mouse.click.up"; direction: "up" } | { type: "mouse.click.down"; direction: "down" } | { type: "mouse.move" } }, }, },} : { types: { events: { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; } | { type: "mouse"; } | { type: "keypress"; }; }; on: { "mouse.*": { actions: ({ event }: { event: { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; }; }) => void; }; }; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ + + types: {} as { +>types : { events: { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; } | { type: "mouse"; } | { type: "keypress"; }; } +> : ^^^^^^^^^^ ^^^ +>{} as { events: | { type: "mouse.click.up"; direction: "up" } | { type: "mouse.click.down"; direction: "down" } | { type: "mouse.move" } | { type: "mouse" } | { type: "keypress" }; } : { events: { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; } | { type: "mouse"; } | { type: "keypress"; }; } +> : ^^^^^^^^^^ ^^^ +>{} : {} +> : ^^ + + events: +>events : { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; } | { type: "mouse"; } | { type: "keypress"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ + + | { type: "mouse.click.up"; direction: "up" } +>type : "mouse.click.up" +> : ^^^^^^^^^^^^^^^^ +>direction : "up" +> : ^^^^ + + | { type: "mouse.click.down"; direction: "down" } +>type : "mouse.click.down" +> : ^^^^^^^^^^^^^^^^^^ +>direction : "down" +> : ^^^^^^ + + | { type: "mouse.move" } +>type : "mouse.move" +> : ^^^^^^^^^^^^ + + | { type: "mouse" } +>type : "mouse" +> : ^^^^^^^ + + | { type: "keypress" }; +>type : "keypress" +> : ^^^^^^^^^^ + + }, + on: { +>on : { "mouse.*": { actions: ({ event }: { event: { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; }; }) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ +>{ "mouse.*": { actions: ({ event }) => { event; // { type: "mouse.click.up"; direction: "up" } | { type: "mouse.click.down"; direction: "down" } | { type: "mouse.move" } }, }, } : { "mouse.*": { actions: ({ event }: { event: { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; }; }) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ + + "mouse.*": { +>"mouse.*" : { actions: ({ event }: { event: { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; }; }) => void; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ +>{ actions: ({ event }) => { event; // { type: "mouse.click.up"; direction: "up" } | { type: "mouse.click.down"; direction: "down" } | { type: "mouse.move" } }, } : { actions: ({ event }: { event: { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; }; }) => void; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ + + actions: ({ event }) => { +>actions : ({ event }: { event: { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; }; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>({ event }) => { event; // { type: "mouse.click.up"; direction: "up" } | { type: "mouse.click.down"; direction: "down" } | { type: "mouse.move" } } : ({ event }: { event: { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; }; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>event : { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ + + event; // { type: "mouse.click.up"; direction: "up" } | { type: "mouse.click.down"; direction: "down" } | { type: "mouse.move" } +>event : { type: "mouse.click.up"; direction: "up"; } | { type: "mouse.click.down"; direction: "down"; } | { type: "mouse.move"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ + + }, + }, + }, +}); + diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType1.ts b/tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType1.ts new file mode 100644 index 0000000000000..e924e33e2f31f --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType1.ts @@ -0,0 +1,48 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/61076 + +type FooEvent = { type: "FOO" }; +type BarEvent = { type: "BAR" }; + +type Input = FooEvent | BarEvent; +type Result = Extract, FooEvent>; + +type EventObject = { + type: string; +}; + +type ActionFunction< + TExpressionEvent extends EventObject, + TEvent extends EventObject, +> = { + (args: { event: TExpressionEvent }): void; + _out_TEvent?: TEvent; +}; + +type TransitionsConfig = { + [K in TEvent["type"]]?: { + actions?: ActionFunction, TEvent>; + }; +}; + +declare function createMachine(config: { + types?: { + events?: TEvent; + }; + on?: TransitionsConfig>; +}): void; + +createMachine({ + types: { + events: {} as Input, + }, + on: { + FOO: { + actions: ({ event }) => { + event; // { type: "FOO"; } + }, + }, + }, +}); diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType2.ts b/tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType2.ts new file mode 100644 index 0000000000000..b49c8f94c2fd1 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType2.ts @@ -0,0 +1,105 @@ +// @strict: true +// @noEmit: true + +type EventObject = { + type: string; +}; + +type FooEvent = { type: "FOO" }; +type BarEvent = { type: "BAR" }; + +type Input = FooEvent | BarEvent; + +type ExtractEventSimplified< + TEvent extends EventObject, + K extends TEvent["type"], +> = string extends TEvent["type"] ? TEvent : Extract; + +type Result = ExtractEventSimplified, "FOO">; + +type EventDescriptorMatches< + TEventType extends string, + TNormalizedDescriptor, +> = TEventType extends TNormalizedDescriptor ? true : false; + +type PartialEventDescriptor = + TEventType extends `${infer TLeading}.${infer TTail}` + ? `${TLeading}.*` | `${TLeading}.${PartialEventDescriptor}` + : never; + +type EventDescriptor = + | TEvent["type"] + | PartialEventDescriptor + | "*"; + +type NormalizeDescriptor = TDescriptor extends "*" + ? string + : TDescriptor extends `${infer TLeading}.*` + ? `${TLeading}.${string}` + : TDescriptor; + +type ExtractEvent< + TEvent extends EventObject, + TDescriptor extends EventDescriptor, +> = string extends TEvent["type"] + ? TEvent + : NormalizeDescriptor extends infer TNormalizedDescriptor + ? TEvent extends any + ? // true is the check type here to match both true and boolean + true extends EventDescriptorMatches + ? TEvent + : never + : never + : never; + +type ActionFunction< + TExpressionEvent extends EventObject, + TEvent extends EventObject, +> = { + (args: { event: TExpressionEvent }): void; + _out_TEvent?: TEvent; +}; + +type TransitionsConfig = { + [K in EventDescriptor]?: { + actions?: ActionFunction, TEvent>; + }; +}; + +declare function createMachine(config: { + types?: { + events?: TEvent; + }; + on?: TransitionsConfig>; +}): void; + +createMachine({ + types: { + events: {} as { type: "FOO" } | { type: "BAR" }, + }, + on: { + FOO: { + actions: ({ event }) => { + event; // { type: "FOO"; } + }, + }, + }, +}); + +createMachine({ + types: {} as { + events: + | { type: "mouse.click.up"; direction: "up" } + | { type: "mouse.click.down"; direction: "down" } + | { type: "mouse.move" } + | { type: "mouse" } + | { type: "keypress" }; + }, + on: { + "mouse.*": { + actions: ({ event }) => { + event; // { type: "mouse.click.up"; direction: "up" } | { type: "mouse.click.down"; direction: "down" } | { type: "mouse.move" } + }, + }, + }, +});