Skip to content

Commit e9939f6

Browse files
committed
Unwrap NoInfer-wrapped unions before conditional type distribution attempt
1 parent 0652664 commit e9939f6

File tree

4 files changed

+320
-0
lines changed

4 files changed

+320
-0
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20422,6 +20422,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2042220422
const newMapper = createTypeMapper(root.outerTypeParameters, typeArguments);
2042320423
const checkType = root.checkType;
2042420424
let distributionType = root.isDistributive ? getReducedType(getMappedType(checkType, newMapper)) : undefined;
20425+
if (distributionType && isNoInferType(distributionType)) {
20426+
distributionType = (distributionType as SubstitutionType).baseType;
20427+
}
2042520428
let narrowingBaseType: Type | undefined;
2042620429
const forNarrowing = distributionType && isNarrowingSubstitutionType(distributionType) && isNarrowableConditionalType(type, mapper);
2042720430
if (forNarrowing) {
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType1.ts] ////
2+
3+
=== noInferVsDistributiveConditionalType1.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/61076
5+
6+
type FooEvent = { type: "FOO" };
7+
>FooEvent : Symbol(FooEvent, Decl(noInferVsDistributiveConditionalType1.ts, 0, 0))
8+
>type : Symbol(type, Decl(noInferVsDistributiveConditionalType1.ts, 2, 17))
9+
10+
type BarEvent = { type: "BAR" };
11+
>BarEvent : Symbol(BarEvent, Decl(noInferVsDistributiveConditionalType1.ts, 2, 32))
12+
>type : Symbol(type, Decl(noInferVsDistributiveConditionalType1.ts, 3, 17))
13+
14+
type Input = FooEvent | BarEvent;
15+
>Input : Symbol(Input, Decl(noInferVsDistributiveConditionalType1.ts, 3, 32))
16+
>FooEvent : Symbol(FooEvent, Decl(noInferVsDistributiveConditionalType1.ts, 0, 0))
17+
>BarEvent : Symbol(BarEvent, Decl(noInferVsDistributiveConditionalType1.ts, 2, 32))
18+
19+
type Result = Extract<NoInfer<Input>, FooEvent>;
20+
>Result : Symbol(Result, Decl(noInferVsDistributiveConditionalType1.ts, 5, 33))
21+
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
22+
>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
23+
>Input : Symbol(Input, Decl(noInferVsDistributiveConditionalType1.ts, 3, 32))
24+
>FooEvent : Symbol(FooEvent, Decl(noInferVsDistributiveConditionalType1.ts, 0, 0))
25+
26+
type EventObject = {
27+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType1.ts, 6, 48))
28+
29+
type: string;
30+
>type : Symbol(type, Decl(noInferVsDistributiveConditionalType1.ts, 8, 20))
31+
32+
};
33+
34+
type ActionFunction<
35+
>ActionFunction : Symbol(ActionFunction, Decl(noInferVsDistributiveConditionalType1.ts, 10, 2))
36+
37+
TExpressionEvent extends EventObject,
38+
>TExpressionEvent : Symbol(TExpressionEvent, Decl(noInferVsDistributiveConditionalType1.ts, 12, 20))
39+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType1.ts, 6, 48))
40+
41+
TEvent extends EventObject,
42+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 13, 39))
43+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType1.ts, 6, 48))
44+
45+
> = {
46+
(args: { event: TExpressionEvent }): void;
47+
>args : Symbol(args, Decl(noInferVsDistributiveConditionalType1.ts, 16, 3))
48+
>event : Symbol(event, Decl(noInferVsDistributiveConditionalType1.ts, 16, 10))
49+
>TExpressionEvent : Symbol(TExpressionEvent, Decl(noInferVsDistributiveConditionalType1.ts, 12, 20))
50+
51+
_out_TEvent?: TEvent;
52+
>_out_TEvent : Symbol(_out_TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 16, 44))
53+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 13, 39))
54+
55+
};
56+
57+
type TransitionsConfig<TEvent extends EventObject> = {
58+
>TransitionsConfig : Symbol(TransitionsConfig, Decl(noInferVsDistributiveConditionalType1.ts, 18, 2))
59+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 20, 23))
60+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType1.ts, 6, 48))
61+
62+
[K in TEvent["type"]]?: {
63+
>K : Symbol(K, Decl(noInferVsDistributiveConditionalType1.ts, 21, 3))
64+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 20, 23))
65+
66+
actions?: ActionFunction<Extract<TEvent, { type: K }>, TEvent>;
67+
>actions : Symbol(actions, Decl(noInferVsDistributiveConditionalType1.ts, 21, 27))
68+
>ActionFunction : Symbol(ActionFunction, Decl(noInferVsDistributiveConditionalType1.ts, 10, 2))
69+
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
70+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 20, 23))
71+
>type : Symbol(type, Decl(noInferVsDistributiveConditionalType1.ts, 22, 46))
72+
>K : Symbol(K, Decl(noInferVsDistributiveConditionalType1.ts, 21, 3))
73+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 20, 23))
74+
75+
};
76+
};
77+
78+
declare function createMachine<TEvent extends EventObject>(config: {
79+
>createMachine : Symbol(createMachine, Decl(noInferVsDistributiveConditionalType1.ts, 24, 2))
80+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 26, 31))
81+
>EventObject : Symbol(EventObject, Decl(noInferVsDistributiveConditionalType1.ts, 6, 48))
82+
>config : Symbol(config, Decl(noInferVsDistributiveConditionalType1.ts, 26, 59))
83+
84+
types?: {
85+
>types : Symbol(types, Decl(noInferVsDistributiveConditionalType1.ts, 26, 68))
86+
87+
events?: TEvent;
88+
>events : Symbol(events, Decl(noInferVsDistributiveConditionalType1.ts, 27, 11))
89+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 26, 31))
90+
91+
};
92+
on?: TransitionsConfig<NoInfer<TEvent>>;
93+
>on : Symbol(on, Decl(noInferVsDistributiveConditionalType1.ts, 29, 4))
94+
>TransitionsConfig : Symbol(TransitionsConfig, Decl(noInferVsDistributiveConditionalType1.ts, 18, 2))
95+
>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
96+
>TEvent : Symbol(TEvent, Decl(noInferVsDistributiveConditionalType1.ts, 26, 31))
97+
98+
}): void;
99+
100+
createMachine({
101+
>createMachine : Symbol(createMachine, Decl(noInferVsDistributiveConditionalType1.ts, 24, 2))
102+
103+
types: {
104+
>types : Symbol(types, Decl(noInferVsDistributiveConditionalType1.ts, 33, 15))
105+
106+
events: {} as Input,
107+
>events : Symbol(events, Decl(noInferVsDistributiveConditionalType1.ts, 34, 10))
108+
>Input : Symbol(Input, Decl(noInferVsDistributiveConditionalType1.ts, 3, 32))
109+
110+
},
111+
on: {
112+
>on : Symbol(on, Decl(noInferVsDistributiveConditionalType1.ts, 36, 4))
113+
114+
FOO: {
115+
>FOO : Symbol(FOO, Decl(noInferVsDistributiveConditionalType1.ts, 37, 7))
116+
117+
actions: ({ event }) => {
118+
>actions : Symbol(actions, Decl(noInferVsDistributiveConditionalType1.ts, 38, 10))
119+
>event : Symbol(event, Decl(noInferVsDistributiveConditionalType1.ts, 39, 17))
120+
121+
event; // { type: "FOO"; }
122+
>event : Symbol(event, Decl(noInferVsDistributiveConditionalType1.ts, 39, 17))
123+
124+
},
125+
},
126+
},
127+
});
128+
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferVsDistributiveConditionalType1.ts] ////
2+
3+
=== noInferVsDistributiveConditionalType1.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/61076
5+
6+
type FooEvent = { type: "FOO" };
7+
>FooEvent : FooEvent
8+
> : ^^^^^^^^
9+
>type : "FOO"
10+
> : ^^^^^
11+
12+
type BarEvent = { type: "BAR" };
13+
>BarEvent : BarEvent
14+
> : ^^^^^^^^
15+
>type : "BAR"
16+
> : ^^^^^
17+
18+
type Input = FooEvent | BarEvent;
19+
>Input : Input
20+
> : ^^^^^
21+
22+
type Result = Extract<NoInfer<Input>, FooEvent>;
23+
>Result : FooEvent
24+
> : ^^^^^^^^
25+
26+
type EventObject = {
27+
>EventObject : EventObject
28+
> : ^^^^^^^^^^^
29+
30+
type: string;
31+
>type : string
32+
> : ^^^^^^
33+
34+
};
35+
36+
type ActionFunction<
37+
>ActionFunction : ActionFunction<TExpressionEvent, TEvent>
38+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
39+
40+
TExpressionEvent extends EventObject,
41+
TEvent extends EventObject,
42+
> = {
43+
(args: { event: TExpressionEvent }): void;
44+
>args : { event: TExpressionEvent; }
45+
> : ^^^^^^^^^ ^^^
46+
>event : TExpressionEvent
47+
> : ^^^^^^^^^^^^^^^^
48+
49+
_out_TEvent?: TEvent;
50+
>_out_TEvent : TEvent | undefined
51+
> : ^^^^^^^^^^^^^^^^^^
52+
53+
};
54+
55+
type TransitionsConfig<TEvent extends EventObject> = {
56+
>TransitionsConfig : TransitionsConfig<TEvent>
57+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^
58+
59+
[K in TEvent["type"]]?: {
60+
actions?: ActionFunction<Extract<TEvent, { type: K }>, TEvent>;
61+
>actions : ActionFunction<Extract<TEvent, { type: K; }>, TEvent> | undefined
62+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
63+
>type : K
64+
> : ^
65+
66+
};
67+
};
68+
69+
declare function createMachine<TEvent extends EventObject>(config: {
70+
>createMachine : <TEvent extends EventObject>(config: { types?: { events?: TEvent; }; on?: TransitionsConfig<NoInfer<TEvent>>; }) => void
71+
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
72+
>config : { types?: { events?: TEvent; }; on?: TransitionsConfig<NoInfer<TEvent>>; }
73+
> : ^^^^^^^^^^ ^^^^^^^ ^^^
74+
75+
types?: {
76+
>types : { events?: TEvent; } | undefined
77+
> : ^^^^^^^^^^^ ^^^^^^^^^^^^^^^
78+
79+
events?: TEvent;
80+
>events : TEvent | undefined
81+
> : ^^^^^^^^^^^^^^^^^^
82+
83+
};
84+
on?: TransitionsConfig<NoInfer<TEvent>>;
85+
>on : TransitionsConfig<NoInfer<TEvent>> | undefined
86+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
87+
88+
}): void;
89+
90+
createMachine({
91+
>createMachine({ types: { events: {} as Input, }, on: { FOO: { actions: ({ event }) => { event; // { type: "FOO"; } }, }, },}) : void
92+
> : ^^^^
93+
>createMachine : <TEvent extends EventObject>(config: { types?: { events?: TEvent; }; on?: TransitionsConfig<NoInfer<TEvent>>; }) => void
94+
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
95+
>{ types: { events: {} as Input, }, on: { FOO: { actions: ({ event }) => { event; // { type: "FOO"; } }, }, },} : { types: { events: Input; }; on: { FOO: { actions: ({ event }: { event: FooEvent; }) => void; }; }; }
96+
> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
97+
98+
types: {
99+
>types : { events: Input; }
100+
> : ^^^^^^^^^^ ^^^
101+
>{ events: {} as Input, } : { events: Input; }
102+
> : ^^^^^^^^^^ ^^^
103+
104+
events: {} as Input,
105+
>events : Input
106+
> : ^^^^^
107+
>{} as Input : Input
108+
> : ^^^^^
109+
>{} : {}
110+
> : ^^
111+
112+
},
113+
on: {
114+
>on : { FOO: { actions: ({ event }: { event: FooEvent; }) => void; }; }
115+
> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
116+
>{ FOO: { actions: ({ event }) => { event; // { type: "FOO"; } }, }, } : { FOO: { actions: ({ event }: { event: FooEvent; }) => void; }; }
117+
> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
118+
119+
FOO: {
120+
>FOO : { actions: ({ event }: { event: FooEvent; }) => void; }
121+
> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
122+
>{ actions: ({ event }) => { event; // { type: "FOO"; } }, } : { actions: ({ event }: { event: FooEvent; }) => void; }
123+
> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
124+
125+
actions: ({ event }) => {
126+
>actions : ({ event }: { event: FooEvent; }) => void
127+
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
128+
>({ event }) => { event; // { type: "FOO"; } } : ({ event }: { event: FooEvent; }) => void
129+
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
130+
>event : FooEvent
131+
> : ^^^^^^^^
132+
133+
event; // { type: "FOO"; }
134+
>event : FooEvent
135+
> : ^^^^^^^^
136+
137+
},
138+
},
139+
},
140+
});
141+
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// https://github.com/microsoft/TypeScript/issues/61076
5+
6+
type FooEvent = { type: "FOO" };
7+
type BarEvent = { type: "BAR" };
8+
9+
type Input = FooEvent | BarEvent;
10+
type Result = Extract<NoInfer<Input>, FooEvent>;
11+
12+
type EventObject = {
13+
type: string;
14+
};
15+
16+
type ActionFunction<
17+
TExpressionEvent extends EventObject,
18+
TEvent extends EventObject,
19+
> = {
20+
(args: { event: TExpressionEvent }): void;
21+
_out_TEvent?: TEvent;
22+
};
23+
24+
type TransitionsConfig<TEvent extends EventObject> = {
25+
[K in TEvent["type"]]?: {
26+
actions?: ActionFunction<Extract<TEvent, { type: K }>, TEvent>;
27+
};
28+
};
29+
30+
declare function createMachine<TEvent extends EventObject>(config: {
31+
types?: {
32+
events?: TEvent;
33+
};
34+
on?: TransitionsConfig<NoInfer<TEvent>>;
35+
}): void;
36+
37+
createMachine({
38+
types: {
39+
events: {} as Input,
40+
},
41+
on: {
42+
FOO: {
43+
actions: ({ event }) => {
44+
event; // { type: "FOO"; }
45+
},
46+
},
47+
},
48+
});

0 commit comments

Comments
 (0)