Skip to content

Commit 193b749

Browse files
authored
Properly propagate silentNeverType in intersections (#45073)
* Properly propagate silentNeverType in intersections * Add regression test
1 parent d0efe90 commit 193b749

File tree

5 files changed

+245
-2
lines changed

5 files changed

+245
-2
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14246,8 +14246,10 @@ namespace ts {
1424614246
// a symbol-like type and a type known to be non-symbol-like, or
1424714247
// a void-like type and a type known to be non-void-like, or
1424814248
// a non-primitive type and a type known to be primitive.
14249-
if (includes & TypeFlags.Never ||
14250-
strictNullChecks && includes & TypeFlags.Nullable && includes & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.IncludesEmptyObject) ||
14249+
if (includes & TypeFlags.Never) {
14250+
return contains(typeSet, silentNeverType) ? silentNeverType : neverType;
14251+
}
14252+
if (strictNullChecks && includes & TypeFlags.Nullable && includes & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.IncludesEmptyObject) ||
1425114253
includes & TypeFlags.NonPrimitive && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NonPrimitive) ||
1425214254
includes & TypeFlags.StringLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.StringLike) ||
1425314255
includes & TypeFlags.NumberLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NumberLike) ||
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//// [silentNeverPropagation.ts]
2+
// Repro from #45041
3+
4+
type ModuleWithState<TState> = {
5+
state: TState;
6+
};
7+
8+
type State = {
9+
a: number;
10+
};
11+
12+
type MoreState = {
13+
z: string;
14+
};
15+
16+
declare function createModule<TState, TActions>(state: TState, actions: TActions): ModuleWithState<TState> & TActions;
17+
18+
declare function convert<TState, TActions>(m: ModuleWithState<TState> & TActions): ModuleWithState<TState & MoreState> & TActions;
19+
20+
const breaks = convert(
21+
createModule({ a: 12 }, { foo() { return true } })
22+
);
23+
24+
breaks.state.a
25+
breaks.state.z
26+
breaks.foo()
27+
28+
29+
//// [silentNeverPropagation.js]
30+
"use strict";
31+
// Repro from #45041
32+
var breaks = convert(createModule({ a: 12 }, { foo: function () { return true; } }));
33+
breaks.state.a;
34+
breaks.state.z;
35+
breaks.foo();
36+
37+
38+
//// [silentNeverPropagation.d.ts]
39+
declare type ModuleWithState<TState> = {
40+
state: TState;
41+
};
42+
declare type State = {
43+
a: number;
44+
};
45+
declare type MoreState = {
46+
z: string;
47+
};
48+
declare function createModule<TState, TActions>(state: TState, actions: TActions): ModuleWithState<TState> & TActions;
49+
declare function convert<TState, TActions>(m: ModuleWithState<TState> & TActions): ModuleWithState<TState & MoreState> & TActions;
50+
declare const breaks: ModuleWithState<{
51+
a: number;
52+
} & MoreState> & ModuleWithState<{
53+
a: number;
54+
}> & {
55+
foo(): true;
56+
};
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
=== tests/cases/compiler/silentNeverPropagation.ts ===
2+
// Repro from #45041
3+
4+
type ModuleWithState<TState> = {
5+
>ModuleWithState : Symbol(ModuleWithState, Decl(silentNeverPropagation.ts, 0, 0))
6+
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 2, 21))
7+
8+
state: TState;
9+
>state : Symbol(state, Decl(silentNeverPropagation.ts, 2, 32))
10+
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 2, 21))
11+
12+
};
13+
14+
type State = {
15+
>State : Symbol(State, Decl(silentNeverPropagation.ts, 4, 2))
16+
17+
a: number;
18+
>a : Symbol(a, Decl(silentNeverPropagation.ts, 6, 14))
19+
20+
};
21+
22+
type MoreState = {
23+
>MoreState : Symbol(MoreState, Decl(silentNeverPropagation.ts, 8, 2))
24+
25+
z: string;
26+
>z : Symbol(z, Decl(silentNeverPropagation.ts, 10, 18))
27+
28+
};
29+
30+
declare function createModule<TState, TActions>(state: TState, actions: TActions): ModuleWithState<TState> & TActions;
31+
>createModule : Symbol(createModule, Decl(silentNeverPropagation.ts, 12, 2))
32+
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 14, 30))
33+
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 14, 37))
34+
>state : Symbol(state, Decl(silentNeverPropagation.ts, 14, 48))
35+
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 14, 30))
36+
>actions : Symbol(actions, Decl(silentNeverPropagation.ts, 14, 62))
37+
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 14, 37))
38+
>ModuleWithState : Symbol(ModuleWithState, Decl(silentNeverPropagation.ts, 0, 0))
39+
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 14, 30))
40+
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 14, 37))
41+
42+
declare function convert<TState, TActions>(m: ModuleWithState<TState> & TActions): ModuleWithState<TState & MoreState> & TActions;
43+
>convert : Symbol(convert, Decl(silentNeverPropagation.ts, 14, 118))
44+
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 16, 25))
45+
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 16, 32))
46+
>m : Symbol(m, Decl(silentNeverPropagation.ts, 16, 43))
47+
>ModuleWithState : Symbol(ModuleWithState, Decl(silentNeverPropagation.ts, 0, 0))
48+
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 16, 25))
49+
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 16, 32))
50+
>ModuleWithState : Symbol(ModuleWithState, Decl(silentNeverPropagation.ts, 0, 0))
51+
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 16, 25))
52+
>MoreState : Symbol(MoreState, Decl(silentNeverPropagation.ts, 8, 2))
53+
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 16, 32))
54+
55+
const breaks = convert(
56+
>breaks : Symbol(breaks, Decl(silentNeverPropagation.ts, 18, 5))
57+
>convert : Symbol(convert, Decl(silentNeverPropagation.ts, 14, 118))
58+
59+
createModule({ a: 12 }, { foo() { return true } })
60+
>createModule : Symbol(createModule, Decl(silentNeverPropagation.ts, 12, 2))
61+
>a : Symbol(a, Decl(silentNeverPropagation.ts, 19, 18))
62+
>foo : Symbol(foo, Decl(silentNeverPropagation.ts, 19, 29))
63+
64+
);
65+
66+
breaks.state.a
67+
>breaks.state.a : Symbol(a, Decl(silentNeverPropagation.ts, 19, 18))
68+
>breaks.state : Symbol(state, Decl(silentNeverPropagation.ts, 2, 32), Decl(silentNeverPropagation.ts, 2, 32))
69+
>breaks : Symbol(breaks, Decl(silentNeverPropagation.ts, 18, 5))
70+
>state : Symbol(state, Decl(silentNeverPropagation.ts, 2, 32), Decl(silentNeverPropagation.ts, 2, 32))
71+
>a : Symbol(a, Decl(silentNeverPropagation.ts, 19, 18))
72+
73+
breaks.state.z
74+
>breaks.state.z : Symbol(z, Decl(silentNeverPropagation.ts, 10, 18))
75+
>breaks.state : Symbol(state, Decl(silentNeverPropagation.ts, 2, 32), Decl(silentNeverPropagation.ts, 2, 32))
76+
>breaks : Symbol(breaks, Decl(silentNeverPropagation.ts, 18, 5))
77+
>state : Symbol(state, Decl(silentNeverPropagation.ts, 2, 32), Decl(silentNeverPropagation.ts, 2, 32))
78+
>z : Symbol(z, Decl(silentNeverPropagation.ts, 10, 18))
79+
80+
breaks.foo()
81+
>breaks.foo : Symbol(foo, Decl(silentNeverPropagation.ts, 19, 29))
82+
>breaks : Symbol(breaks, Decl(silentNeverPropagation.ts, 18, 5))
83+
>foo : Symbol(foo, Decl(silentNeverPropagation.ts, 19, 29))
84+
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
=== tests/cases/compiler/silentNeverPropagation.ts ===
2+
// Repro from #45041
3+
4+
type ModuleWithState<TState> = {
5+
>ModuleWithState : ModuleWithState<TState>
6+
7+
state: TState;
8+
>state : TState
9+
10+
};
11+
12+
type State = {
13+
>State : State
14+
15+
a: number;
16+
>a : number
17+
18+
};
19+
20+
type MoreState = {
21+
>MoreState : MoreState
22+
23+
z: string;
24+
>z : string
25+
26+
};
27+
28+
declare function createModule<TState, TActions>(state: TState, actions: TActions): ModuleWithState<TState> & TActions;
29+
>createModule : <TState, TActions>(state: TState, actions: TActions) => ModuleWithState<TState> & TActions
30+
>state : TState
31+
>actions : TActions
32+
33+
declare function convert<TState, TActions>(m: ModuleWithState<TState> & TActions): ModuleWithState<TState & MoreState> & TActions;
34+
>convert : <TState, TActions>(m: ModuleWithState<TState> & TActions) => ModuleWithState<TState & MoreState> & TActions
35+
>m : ModuleWithState<TState> & TActions
36+
37+
const breaks = convert(
38+
>breaks : ModuleWithState<{ a: number; } & MoreState> & ModuleWithState<{ a: number; }> & { foo(): true; }
39+
>convert( createModule({ a: 12 }, { foo() { return true } })) : ModuleWithState<{ a: number; } & MoreState> & ModuleWithState<{ a: number; }> & { foo(): true; }
40+
>convert : <TState, TActions>(m: ModuleWithState<TState> & TActions) => ModuleWithState<TState & MoreState> & TActions
41+
42+
createModule({ a: 12 }, { foo() { return true } })
43+
>createModule({ a: 12 }, { foo() { return true } }) : ModuleWithState<{ a: number; }> & { foo(): true; }
44+
>createModule : <TState, TActions>(state: TState, actions: TActions) => ModuleWithState<TState> & TActions
45+
>{ a: 12 } : { a: number; }
46+
>a : number
47+
>12 : 12
48+
>{ foo() { return true } } : { foo(): true; }
49+
>foo : () => true
50+
>true : true
51+
52+
);
53+
54+
breaks.state.a
55+
>breaks.state.a : number
56+
>breaks.state : { a: number; } & MoreState
57+
>breaks : ModuleWithState<{ a: number; } & MoreState> & ModuleWithState<{ a: number; }> & { foo(): true; }
58+
>state : { a: number; } & MoreState
59+
>a : number
60+
61+
breaks.state.z
62+
>breaks.state.z : string
63+
>breaks.state : { a: number; } & MoreState
64+
>breaks : ModuleWithState<{ a: number; } & MoreState> & ModuleWithState<{ a: number; }> & { foo(): true; }
65+
>state : { a: number; } & MoreState
66+
>z : string
67+
68+
breaks.foo()
69+
>breaks.foo() : true
70+
>breaks.foo : () => true
71+
>breaks : ModuleWithState<{ a: number; } & MoreState> & ModuleWithState<{ a: number; }> & { foo(): true; }
72+
>foo : () => true
73+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// @strict: true
2+
// @declaration: true
3+
4+
// Repro from #45041
5+
6+
type ModuleWithState<TState> = {
7+
state: TState;
8+
};
9+
10+
type State = {
11+
a: number;
12+
};
13+
14+
type MoreState = {
15+
z: string;
16+
};
17+
18+
declare function createModule<TState, TActions>(state: TState, actions: TActions): ModuleWithState<TState> & TActions;
19+
20+
declare function convert<TState, TActions>(m: ModuleWithState<TState> & TActions): ModuleWithState<TState & MoreState> & TActions;
21+
22+
const breaks = convert(
23+
createModule({ a: 12 }, { foo() { return true } })
24+
);
25+
26+
breaks.state.a
27+
breaks.state.z
28+
breaks.foo()

0 commit comments

Comments
 (0)