Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0737761

Browse files
committedJan 30, 2025·
unwrap them in canTailRecurse too
1 parent e9939f6 commit 0737761

File tree

4 files changed

+543
-1
lines changed

4 files changed

+543
-1
lines changed
 

‎src/compiler/checker.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -19328,7 +19328,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1932819328
const typeParamMapper = combineTypeMappers((newType as ConditionalType).mapper, newMapper);
1932919329
const typeArguments = map(newRoot.outerTypeParameters, t => getMappedType(t, typeParamMapper));
1933019330
const newRootMapper = createTypeMapper(newRoot.outerTypeParameters, typeArguments);
19331-
const newCheckType = newRoot.isDistributive ? getMappedType(newRoot.checkType, newRootMapper) : undefined;
19331+
let newCheckType = newRoot.isDistributive ? getMappedType(newRoot.checkType, newRootMapper) : undefined;
19332+
if (newCheckType && isNoInferType(newCheckType)) {
19333+
newCheckType = (newCheckType as SubstitutionType).baseType;
19334+
}
1933219335
if (!newCheckType || newCheckType === newRoot.checkType || !(newCheckType.flags & (TypeFlags.Union | TypeFlags.Never))) {
1933319336
root = newRoot;
1933419337
mapper = newRootMapper;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType2.ts] ////
2+
3+
=== noInferVsDistributiveConditionalType2.ts ===
4+
type EventObject = {
5+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0))
6+
7+
type: string;
8+
>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 0, 20))
9+
10+
};
11+
12+
type FooEvent = { type: "FOO" };
13+
>FooEvent : Symbol(FooEvent, Decl(noInferVsDistributiveConditionalType2.ts, 2, 2))
14+
>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 4, 17))
15+
16+
type BarEvent = { type: "BAR" };
17+
>BarEvent : Symbol(BarEvent, Decl(noInferVsDistributiveConditionalType2.ts, 4, 32))
18+
>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 5, 17))
19+
20+
type Input = FooEvent | BarEvent;
21+
>Input : Symbol(Input, Decl(noInferVsDistributiveConditionalType2.ts, 5, 32))
22+
>FooEvent : Symbol(FooEvent, Decl(noInferVsDistributiveConditionalType2.ts, 2, 2))
23+
>BarEvent : Symbol(BarEvent, Decl(noInferVsDistributiveConditionalType2.ts, 4, 32))
24+
25+
type ExtractEventSimplified<
26+
>ExtractEventSimplified : Symbol(ExtractEventSimplified, Decl(noInferVsDistributiveConditionalType2.ts, 7, 33))
27+
28+
TEvent extends EventObject,
29+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 9, 28))
30+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0))
31+
32+
K extends TEvent["type"],
33+
>K : Symbol(K, Decl(noInferVsDistributiveConditionalType2.ts, 10, 29))
34+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 9, 28))
35+
36+
> = string extends TEvent["type"] ? TEvent : Extract<TEvent, { type: K }>;
37+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 9, 28))
38+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 9, 28))
39+
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
40+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 9, 28))
41+
>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 12, 62))
42+
>K : Symbol(K, Decl(noInferVsDistributiveConditionalType2.ts, 10, 29))
43+
44+
type Result = ExtractEventSimplified<NoInfer<Input>, "FOO">;
45+
>Result : Symbol(Result, Decl(noInferVsDistributiveConditionalType2.ts, 12, 74))
46+
>ExtractEventSimplified : Symbol(ExtractEventSimplified, Decl(noInferVsDistributiveConditionalType2.ts, 7, 33))
47+
>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
48+
>Input : Symbol(Input, Decl(noInferVsDistributiveConditionalType2.ts, 5, 32))
49+
50+
type EventDescriptorMatches<
51+
>EventDescriptorMatches : Symbol(EventDescriptorMatches, Decl(noInferVsDistributiveConditionalType2.ts, 14, 60))
52+
53+
TEventType extends string,
54+
>TEventType : Symbol(TEventType, Decl(noInferVsDistributiveConditionalType2.ts, 16, 28))
55+
56+
TNormalizedDescriptor,
57+
>TNormalizedDescriptor : Symbol(TNormalizedDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 17, 28))
58+
59+
> = TEventType extends TNormalizedDescriptor ? true : false;
60+
>TEventType : Symbol(TEventType, Decl(noInferVsDistributiveConditionalType2.ts, 16, 28))
61+
>TNormalizedDescriptor : Symbol(TNormalizedDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 17, 28))
62+
63+
type PartialEventDescriptor<TEventType extends string> =
64+
>PartialEventDescriptor : Symbol(PartialEventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 19, 60))
65+
>TEventType : Symbol(TEventType, Decl(noInferVsDistributiveConditionalType2.ts, 21, 28))
66+
67+
TEventType extends `${infer TLeading}.${infer TTail}`
68+
>TEventType : Symbol(TEventType, Decl(noInferVsDistributiveConditionalType2.ts, 21, 28))
69+
>TLeading : Symbol(TLeading, Decl(noInferVsDistributiveConditionalType2.ts, 22, 29))
70+
>TTail : Symbol(TTail, Decl(noInferVsDistributiveConditionalType2.ts, 22, 47))
71+
72+
? `${TLeading}.*` | `${TLeading}.${PartialEventDescriptor<TTail>}`
73+
>TLeading : Symbol(TLeading, Decl(noInferVsDistributiveConditionalType2.ts, 22, 29))
74+
>TLeading : Symbol(TLeading, Decl(noInferVsDistributiveConditionalType2.ts, 22, 29))
75+
>PartialEventDescriptor : Symbol(PartialEventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 19, 60))
76+
>TTail : Symbol(TTail, Decl(noInferVsDistributiveConditionalType2.ts, 22, 47))
77+
78+
: never;
79+
80+
type EventDescriptor<TEvent extends EventObject> =
81+
>EventDescriptor : Symbol(EventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 24, 12))
82+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 26, 21))
83+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0))
84+
85+
| TEvent["type"]
86+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 26, 21))
87+
88+
| PartialEventDescriptor<TEvent["type"]>
89+
>PartialEventDescriptor : Symbol(PartialEventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 19, 60))
90+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 26, 21))
91+
92+
| "*";
93+
94+
type NormalizeDescriptor<TDescriptor extends string> = TDescriptor extends "*"
95+
>NormalizeDescriptor : Symbol(NormalizeDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 29, 8))
96+
>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 31, 25))
97+
>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 31, 25))
98+
99+
? string
100+
: TDescriptor extends `${infer TLeading}.*`
101+
>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 31, 25))
102+
>TLeading : Symbol(TLeading, Decl(noInferVsDistributiveConditionalType2.ts, 33, 32))
103+
104+
? `${TLeading}.${string}`
105+
>TLeading : Symbol(TLeading, Decl(noInferVsDistributiveConditionalType2.ts, 33, 32))
106+
107+
: TDescriptor;
108+
>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 31, 25))
109+
110+
type ExtractEvent<
111+
>ExtractEvent : Symbol(ExtractEvent, Decl(noInferVsDistributiveConditionalType2.ts, 35, 16))
112+
113+
TEvent extends EventObject,
114+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18))
115+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0))
116+
117+
TDescriptor extends EventDescriptor<TEvent>,
118+
>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 38, 29))
119+
>EventDescriptor : Symbol(EventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 24, 12))
120+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18))
121+
122+
> = string extends TEvent["type"]
123+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18))
124+
125+
? TEvent
126+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18))
127+
128+
: NormalizeDescriptor<TDescriptor> extends infer TNormalizedDescriptor
129+
>NormalizeDescriptor : Symbol(NormalizeDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 29, 8))
130+
>TDescriptor : Symbol(TDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 38, 29))
131+
>TNormalizedDescriptor : Symbol(TNormalizedDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 42, 50))
132+
133+
? TEvent extends any
134+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18))
135+
136+
? // true is the check type here to match both true and boolean
137+
true extends EventDescriptorMatches<TEvent["type"], TNormalizedDescriptor>
138+
>EventDescriptorMatches : Symbol(EventDescriptorMatches, Decl(noInferVsDistributiveConditionalType2.ts, 14, 60))
139+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18))
140+
>TNormalizedDescriptor : Symbol(TNormalizedDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 42, 50))
141+
142+
? TEvent
143+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 37, 18))
144+
145+
: never
146+
: never
147+
: never;
148+
149+
type ActionFunction<
150+
>ActionFunction : Symbol(ActionFunction, Decl(noInferVsDistributiveConditionalType2.ts, 49, 10))
151+
152+
TExpressionEvent extends EventObject,
153+
>TExpressionEvent : Symbol(TExpressionEvent, Decl(noInferVsDistributiveConditionalType2.ts, 51, 20))
154+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0))
155+
156+
TEvent extends EventObject,
157+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 52, 39))
158+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0))
159+
160+
> = {
161+
(args: { event: TExpressionEvent }): void;
162+
>args : Symbol(args, Decl(noInferVsDistributiveConditionalType2.ts, 55, 3))
163+
>event : Symbol(event, Decl(noInferVsDistributiveConditionalType2.ts, 55, 10))
164+
>TExpressionEvent : Symbol(TExpressionEvent, Decl(noInferVsDistributiveConditionalType2.ts, 51, 20))
165+
166+
_out_TEvent?: TEvent;
167+
>_out_TEvent : Symbol(_out_TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 55, 44))
168+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 52, 39))
169+
170+
};
171+
172+
type TransitionsConfig<TEvent extends EventObject> = {
173+
>TransitionsConfig : Symbol(TransitionsConfig, Decl(noInferVsDistributiveConditionalType2.ts, 57, 2))
174+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 59, 23))
175+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0))
176+
177+
[K in EventDescriptor<TEvent>]?: {
178+
>K : Symbol(K, Decl(noInferVsDistributiveConditionalType2.ts, 60, 3))
179+
>EventDescriptor : Symbol(EventDescriptor, Decl(noInferVsDistributiveConditionalType2.ts, 24, 12))
180+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 59, 23))
181+
182+
actions?: ActionFunction<ExtractEvent<TEvent, K>, TEvent>;
183+
>actions : Symbol(actions, Decl(noInferVsDistributiveConditionalType2.ts, 60, 36))
184+
>ActionFunction : Symbol(ActionFunction, Decl(noInferVsDistributiveConditionalType2.ts, 49, 10))
185+
>ExtractEvent : Symbol(ExtractEvent, Decl(noInferVsDistributiveConditionalType2.ts, 35, 16))
186+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 59, 23))
187+
>K : Symbol(K, Decl(noInferVsDistributiveConditionalType2.ts, 60, 3))
188+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 59, 23))
189+
190+
};
191+
};
192+
193+
declare function createMachine<TEvent extends EventObject>(config: {
194+
>createMachine : Symbol(createMachine, Decl(noInferVsDistributiveConditionalType2.ts, 63, 2))
195+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 65, 31))
196+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType2.ts, 0, 0))
197+
>config : Symbol(config, Decl(noInferVsDistributiveConditionalType2.ts, 65, 59))
198+
199+
types?: {
200+
>types : Symbol(types, Decl(noInferVsDistributiveConditionalType2.ts, 65, 68))
201+
202+
events?: TEvent;
203+
>events : Symbol(events, Decl(noInferVsDistributiveConditionalType2.ts, 66, 11))
204+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 65, 31))
205+
206+
};
207+
on?: TransitionsConfig<NoInfer<TEvent>>;
208+
>on : Symbol(on, Decl(noInferVsDistributiveConditionalType2.ts, 68, 4))
209+
>TransitionsConfig : Symbol(TransitionsConfig, Decl(noInferVsDistributiveConditionalType2.ts, 57, 2))
210+
>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
211+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType2.ts, 65, 31))
212+
213+
}): void;
214+
215+
createMachine({
216+
>createMachine : Symbol(createMachine, Decl(noInferVsDistributiveConditionalType2.ts, 63, 2))
217+
218+
types: {
219+
>types : Symbol(types, Decl(noInferVsDistributiveConditionalType2.ts, 72, 15))
220+
221+
events: {} as { type: "FOO" } | { type: "BAR" },
222+
>events : Symbol(events, Decl(noInferVsDistributiveConditionalType2.ts, 73, 10))
223+
>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 74, 19))
224+
>type : Symbol(type, Decl(noInferVsDistributiveConditionalType2.ts, 74, 37))
225+
226+
},
227+
on: {
228+
>on : Symbol(on, Decl(noInferVsDistributiveConditionalType2.ts, 75, 4))
229+
230+
FOO: {
231+
>FOO : Symbol(FOO, Decl(noInferVsDistributiveConditionalType2.ts, 76, 7))
232+
233+
actions: ({ event }) => {
234+
>actions : Symbol(actions, Decl(noInferVsDistributiveConditionalType2.ts, 77, 10))
235+
>event : Symbol(event, Decl(noInferVsDistributiveConditionalType2.ts, 78, 17))
236+
237+
event; // { type: "FOO"; }
238+
>event : Symbol(event, Decl(noInferVsDistributiveConditionalType2.ts, 78, 17))
239+
240+
},
241+
},
242+
},
243+
});
244+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType2.ts] ////
2+
3+
=== noInferVsDistributiveConditionalType2.ts ===
4+
type EventObject = {
5+
>EventObject : EventObject
6+
> : ^^^^^^^^^^^
7+
8+
type: string;
9+
>type : string
10+
> : ^^^^^^
11+
12+
};
13+
14+
type FooEvent = { type: "FOO" };
15+
>FooEvent : FooEvent
16+
> : ^^^^^^^^
17+
>type : "FOO"
18+
> : ^^^^^
19+
20+
type BarEvent = { type: "BAR" };
21+
>BarEvent : BarEvent
22+
> : ^^^^^^^^
23+
>type : "BAR"
24+
> : ^^^^^
25+
26+
type Input = FooEvent | BarEvent;
27+
>Input : Input
28+
> : ^^^^^
29+
30+
type ExtractEventSimplified<
31+
>ExtractEventSimplified : ExtractEventSimplified<TEvent, K>
32+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33+
34+
TEvent extends EventObject,
35+
K extends TEvent["type"],
36+
> = string extends TEvent["type"] ? TEvent : Extract<TEvent, { type: K }>;
37+
>type : K
38+
> : ^
39+
40+
type Result = ExtractEventSimplified<NoInfer<Input>, "FOO">;
41+
>Result : FooEvent
42+
> : ^^^^^^^^
43+
44+
type EventDescriptorMatches<
45+
>EventDescriptorMatches : EventDescriptorMatches<TEventType, TNormalizedDescriptor>
46+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47+
48+
TEventType extends string,
49+
TNormalizedDescriptor,
50+
> = TEventType extends TNormalizedDescriptor ? true : false;
51+
>true : true
52+
> : ^^^^
53+
>false : false
54+
> : ^^^^^
55+
56+
type PartialEventDescriptor<TEventType extends string> =
57+
>PartialEventDescriptor : PartialEventDescriptor<TEventType>
58+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
59+
60+
TEventType extends `${infer TLeading}.${infer TTail}`
61+
? `${TLeading}.*` | `${TLeading}.${PartialEventDescriptor<TTail>}`
62+
: never;
63+
64+
type EventDescriptor<TEvent extends EventObject> =
65+
>EventDescriptor : EventDescriptor<TEvent>
66+
> : ^^^^^^^^^^^^^^^^^^^^^^^
67+
68+
| TEvent["type"]
69+
| PartialEventDescriptor<TEvent["type"]>
70+
| "*";
71+
72+
type NormalizeDescriptor<TDescriptor extends string> = TDescriptor extends "*"
73+
>NormalizeDescriptor : NormalizeDescriptor<TDescriptor>
74+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
75+
76+
? string
77+
: TDescriptor extends `${infer TLeading}.*`
78+
? `${TLeading}.${string}`
79+
: TDescriptor;
80+
81+
type ExtractEvent<
82+
>ExtractEvent : ExtractEvent<TEvent, TDescriptor>
83+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
84+
85+
TEvent extends EventObject,
86+
TDescriptor extends EventDescriptor<TEvent>,
87+
> = string extends TEvent["type"]
88+
? TEvent
89+
: NormalizeDescriptor<TDescriptor> extends infer TNormalizedDescriptor
90+
? TEvent extends any
91+
? // true is the check type here to match both true and boolean
92+
true extends EventDescriptorMatches<TEvent["type"], TNormalizedDescriptor>
93+
>true : true
94+
> : ^^^^
95+
96+
? TEvent
97+
: never
98+
: never
99+
: never;
100+
101+
type ActionFunction<
102+
>ActionFunction : ActionFunction<TExpressionEvent, TEvent>
103+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
104+
105+
TExpressionEvent extends EventObject,
106+
TEvent extends EventObject,
107+
> = {
108+
(args: { event: TExpressionEvent }): void;
109+
>args : { event: TExpressionEvent; }
110+
> : ^^^^^^^^^ ^^^
111+
>event : TExpressionEvent
112+
> : ^^^^^^^^^^^^^^^^
113+
114+
_out_TEvent?: TEvent;
115+
>_out_TEvent : TEvent | undefined
116+
> : ^^^^^^^^^^^^^^^^^^
117+
118+
};
119+
120+
type TransitionsConfig<TEvent extends EventObject> = {
121+
>TransitionsConfig : TransitionsConfig<TEvent>
122+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^
123+
124+
[K in EventDescriptor<TEvent>]?: {
125+
actions?: ActionFunction<ExtractEvent<TEvent, K>, TEvent>;
126+
>actions : ActionFunction<ExtractEvent<TEvent, K>, TEvent> | undefined
127+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
128+
129+
};
130+
};
131+
132+
declare function createMachine<TEvent extends EventObject>(config: {
133+
>createMachine : <TEvent extends EventObject>(config: { types?: { events?: TEvent; }; on?: TransitionsConfig<NoInfer<TEvent>>; }) => void
134+
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
135+
>config : { types?: { events?: TEvent; }; on?: TransitionsConfig<NoInfer<TEvent>>; }
136+
> : ^^^^^^^^^^ ^^^^^^^ ^^^
137+
138+
types?: {
139+
>types : { events?: TEvent; } | undefined
140+
> : ^^^^^^^^^^^ ^^^^^^^^^^^^^^^
141+
142+
events?: TEvent;
143+
>events : TEvent | undefined
144+
> : ^^^^^^^^^^^^^^^^^^
145+
146+
};
147+
on?: TransitionsConfig<NoInfer<TEvent>>;
148+
>on : TransitionsConfig<NoInfer<TEvent>> | undefined
149+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
150+
151+
}): void;
152+
153+
createMachine({
154+
>createMachine({ types: { events: {} as { type: "FOO" } | { type: "BAR" }, }, on: { FOO: { actions: ({ event }) => { event; // { type: "FOO"; } }, }, },}) : void
155+
> : ^^^^
156+
>createMachine : <TEvent extends EventObject>(config: { types?: { events?: TEvent; }; on?: TransitionsConfig<NoInfer<TEvent>>; }) => void
157+
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
158+
>{ 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; }; }; }
159+
> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
160+
161+
types: {
162+
>types : { events: { type: "FOO"; } | { type: "BAR"; }; }
163+
> : ^^^^^^^^^^ ^^^
164+
>{ events: {} as { type: "FOO" } | { type: "BAR" }, } : { events: { type: "FOO"; } | { type: "BAR"; }; }
165+
> : ^^^^^^^^^^ ^^^
166+
167+
events: {} as { type: "FOO" } | { type: "BAR" },
168+
>events : { type: "FOO"; } | { type: "BAR"; }
169+
> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^
170+
>{} as { type: "FOO" } | { type: "BAR" } : { type: "FOO"; } | { type: "BAR"; }
171+
> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^
172+
>{} : {}
173+
> : ^^
174+
>type : "FOO"
175+
> : ^^^^^
176+
>type : "BAR"
177+
> : ^^^^^
178+
179+
},
180+
on: {
181+
>on : { FOO: { actions: ({ event }: { event: { type: "FOO"; }; }) => void; }; }
182+
> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
183+
>{ FOO: { actions: ({ event }) => { event; // { type: "FOO"; } }, }, } : { FOO: { actions: ({ event }: { event: { type: "FOO"; }; }) => void; }; }
184+
> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
185+
186+
FOO: {
187+
>FOO : { actions: ({ event }: { event: { type: "FOO"; }; }) => void; }
188+
> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
189+
>{ actions: ({ event }) => { event; // { type: "FOO"; } }, } : { actions: ({ event }: { event: { type: "FOO"; }; }) => void; }
190+
> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
191+
192+
actions: ({ event }) => {
193+
>actions : ({ event }: { event: { type: "FOO"; }; }) => void
194+
> : ^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
195+
>({ event }) => { event; // { type: "FOO"; } } : ({ event }: { event: { type: "FOO"; }; }) => void
196+
> : ^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
197+
>event : { type: "FOO"; }
198+
> : ^^^^^^^^ ^^^
199+
200+
event; // { type: "FOO"; }
201+
>event : { type: "FOO"; }
202+
> : ^^^^^^^^ ^^^
203+
204+
},
205+
},
206+
},
207+
});
208+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
type EventObject = {
5+
type: string;
6+
};
7+
8+
type FooEvent = { type: "FOO" };
9+
type BarEvent = { type: "BAR" };
10+
11+
type Input = FooEvent | BarEvent;
12+
13+
type ExtractEventSimplified<
14+
TEvent extends EventObject,
15+
K extends TEvent["type"],
16+
> = string extends TEvent["type"] ? TEvent : Extract<TEvent, { type: K }>;
17+
18+
type Result = ExtractEventSimplified<NoInfer<Input>, "FOO">;
19+
20+
type EventDescriptorMatches<
21+
TEventType extends string,
22+
TNormalizedDescriptor,
23+
> = TEventType extends TNormalizedDescriptor ? true : false;
24+
25+
type PartialEventDescriptor<TEventType extends string> =
26+
TEventType extends `${infer TLeading}.${infer TTail}`
27+
? `${TLeading}.*` | `${TLeading}.${PartialEventDescriptor<TTail>}`
28+
: never;
29+
30+
type EventDescriptor<TEvent extends EventObject> =
31+
| TEvent["type"]
32+
| PartialEventDescriptor<TEvent["type"]>
33+
| "*";
34+
35+
type NormalizeDescriptor<TDescriptor extends string> = TDescriptor extends "*"
36+
? string
37+
: TDescriptor extends `${infer TLeading}.*`
38+
? `${TLeading}.${string}`
39+
: TDescriptor;
40+
41+
type ExtractEvent<
42+
TEvent extends EventObject,
43+
TDescriptor extends EventDescriptor<TEvent>,
44+
> = string extends TEvent["type"]
45+
? TEvent
46+
: NormalizeDescriptor<TDescriptor> extends infer TNormalizedDescriptor
47+
? TEvent extends any
48+
? // true is the check type here to match both true and boolean
49+
true extends EventDescriptorMatches<TEvent["type"], TNormalizedDescriptor>
50+
? TEvent
51+
: never
52+
: never
53+
: never;
54+
55+
type ActionFunction<
56+
TExpressionEvent extends EventObject,
57+
TEvent extends EventObject,
58+
> = {
59+
(args: { event: TExpressionEvent }): void;
60+
_out_TEvent?: TEvent;
61+
};
62+
63+
type TransitionsConfig<TEvent extends EventObject> = {
64+
[K in EventDescriptor<TEvent>]?: {
65+
actions?: ActionFunction<ExtractEvent<TEvent, K>, TEvent>;
66+
};
67+
};
68+
69+
declare function createMachine<TEvent extends EventObject>(config: {
70+
types?: {
71+
events?: TEvent;
72+
};
73+
on?: TransitionsConfig<NoInfer<TEvent>>;
74+
}): void;
75+
76+
createMachine({
77+
types: {
78+
events: {} as { type: "FOO" } | { type: "BAR" },
79+
},
80+
on: {
81+
FOO: {
82+
actions: ({ event }) => {
83+
event; // { type: "FOO"; }
84+
},
85+
},
86+
},
87+
});

0 commit comments

Comments
 (0)
Please sign in to comment.