Skip to content

Commit 37bafa5

Browse files
authored
Exclude comparable relation from literal type relation optimization (#53419)
1 parent 25550bd commit 37bafa5

File tree

4 files changed

+187
-2
lines changed

4 files changed

+187
-2
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20899,14 +20899,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2089920899
if (containsType(targetTypes, source)) {
2090020900
return Ternary.True;
2090120901
}
20902-
if (getObjectFlags(target) & ObjectFlags.PrimitiveUnion && !(source.flags & TypeFlags.EnumLiteral) && (
20902+
if (relation !== comparableRelation && getObjectFlags(target) & ObjectFlags.PrimitiveUnion && !(source.flags & TypeFlags.EnumLiteral) && (
2090320903
source.flags & (TypeFlags.StringLiteral | TypeFlags.BooleanLiteral | TypeFlags.BigIntLiteral) ||
2090420904
(relation === subtypeRelation || relation === strictSubtypeRelation) && source.flags & TypeFlags.NumberLiteral)) {
2090520905
// When relating a literal type to a union of primitive types, we know the relation is false unless
2090620906
// the union contains the base primitive type or the literal type in one of its fresh/regular forms.
2090720907
// We exclude numeric literals for non-subtype relations because numeric literals are assignable to
2090820908
// numeric enum literals with the same value. Similarly, we exclude enum literal types because
20909-
// identically named enum types are related (see isEmumTypeRelatedTo).
20909+
// identically named enum types are related (see isEnumTypeRelatedTo). We exclude the comparable
20910+
// relation in entirety because it needs to be checked in both directions.
2091020911
const alternateForm = source === (source as StringLiteralType).regularType ? (source as StringLiteralType).freshType : (source as StringLiteralType).regularType;
2091120912
const primitive = source.flags & TypeFlags.StringLiteral ? stringType :
2091220913
source.flags & TypeFlags.NumberLiteral ? numberType :
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
=== tests/cases/compiler/comparableRelationBidirectional.ts ===
2+
enum AutomationMode {
3+
>AutomationMode : Symbol(AutomationMode, Decl(comparableRelationBidirectional.ts, 0, 0))
4+
5+
NONE = "",
6+
>NONE : Symbol(AutomationMode.NONE, Decl(comparableRelationBidirectional.ts, 0, 21))
7+
8+
TIME = "time",
9+
>TIME : Symbol(AutomationMode.TIME, Decl(comparableRelationBidirectional.ts, 1, 14))
10+
11+
SYSTEM = "system",
12+
>SYSTEM : Symbol(AutomationMode.SYSTEM, Decl(comparableRelationBidirectional.ts, 2, 18))
13+
14+
LOCATION = "location",
15+
>LOCATION : Symbol(AutomationMode.LOCATION, Decl(comparableRelationBidirectional.ts, 3, 22))
16+
}
17+
18+
interface ThemePreset {
19+
>ThemePreset : Symbol(ThemePreset, Decl(comparableRelationBidirectional.ts, 5, 1))
20+
21+
id: string;
22+
>id : Symbol(ThemePreset.id, Decl(comparableRelationBidirectional.ts, 7, 23))
23+
}
24+
25+
interface Automation {
26+
>Automation : Symbol(Automation, Decl(comparableRelationBidirectional.ts, 9, 1))
27+
28+
mode: AutomationMode;
29+
>mode : Symbol(Automation.mode, Decl(comparableRelationBidirectional.ts, 11, 22))
30+
>AutomationMode : Symbol(AutomationMode, Decl(comparableRelationBidirectional.ts, 0, 0))
31+
}
32+
33+
interface UserSettings {
34+
>UserSettings : Symbol(UserSettings, Decl(comparableRelationBidirectional.ts, 13, 1))
35+
36+
presets: ThemePreset[];
37+
>presets : Symbol(UserSettings.presets, Decl(comparableRelationBidirectional.ts, 15, 24))
38+
>ThemePreset : Symbol(ThemePreset, Decl(comparableRelationBidirectional.ts, 5, 1))
39+
40+
automation: Automation;
41+
>automation : Symbol(UserSettings.automation, Decl(comparableRelationBidirectional.ts, 16, 27))
42+
>Automation : Symbol(Automation, Decl(comparableRelationBidirectional.ts, 9, 1))
43+
}
44+
45+
interface ExtensionData {
46+
>ExtensionData : Symbol(ExtensionData, Decl(comparableRelationBidirectional.ts, 18, 1))
47+
48+
settings: UserSettings;
49+
>settings : Symbol(ExtensionData.settings, Decl(comparableRelationBidirectional.ts, 20, 25))
50+
>UserSettings : Symbol(UserSettings, Decl(comparableRelationBidirectional.ts, 13, 1))
51+
}
52+
53+
export function getMockData(): ExtensionData {
54+
>getMockData : Symbol(getMockData, Decl(comparableRelationBidirectional.ts, 22, 1))
55+
>ExtensionData : Symbol(ExtensionData, Decl(comparableRelationBidirectional.ts, 18, 1))
56+
57+
return {
58+
settings: {
59+
>settings : Symbol(settings, Decl(comparableRelationBidirectional.ts, 25, 12))
60+
61+
presets: [],
62+
>presets : Symbol(presets, Decl(comparableRelationBidirectional.ts, 26, 19))
63+
64+
automation: {
65+
>automation : Symbol(automation, Decl(comparableRelationBidirectional.ts, 27, 24))
66+
67+
mode: "",
68+
>mode : Symbol(mode, Decl(comparableRelationBidirectional.ts, 28, 25))
69+
70+
},
71+
} as UserSettings,
72+
>UserSettings : Symbol(UserSettings, Decl(comparableRelationBidirectional.ts, 13, 1))
73+
}
74+
}
75+
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
=== tests/cases/compiler/comparableRelationBidirectional.ts ===
2+
enum AutomationMode {
3+
>AutomationMode : AutomationMode
4+
5+
NONE = "",
6+
>NONE : AutomationMode.NONE
7+
>"" : ""
8+
9+
TIME = "time",
10+
>TIME : AutomationMode.TIME
11+
>"time" : "time"
12+
13+
SYSTEM = "system",
14+
>SYSTEM : AutomationMode.SYSTEM
15+
>"system" : "system"
16+
17+
LOCATION = "location",
18+
>LOCATION : AutomationMode.LOCATION
19+
>"location" : "location"
20+
}
21+
22+
interface ThemePreset {
23+
id: string;
24+
>id : string
25+
}
26+
27+
interface Automation {
28+
mode: AutomationMode;
29+
>mode : AutomationMode
30+
}
31+
32+
interface UserSettings {
33+
presets: ThemePreset[];
34+
>presets : ThemePreset[]
35+
36+
automation: Automation;
37+
>automation : Automation
38+
}
39+
40+
interface ExtensionData {
41+
settings: UserSettings;
42+
>settings : UserSettings
43+
}
44+
45+
export function getMockData(): ExtensionData {
46+
>getMockData : () => ExtensionData
47+
48+
return {
49+
>{ settings: { presets: [], automation: { mode: "", }, } as UserSettings, } : { settings: UserSettings; }
50+
51+
settings: {
52+
>settings : UserSettings
53+
>{ presets: [], automation: { mode: "", }, } as UserSettings : UserSettings
54+
>{ presets: [], automation: { mode: "", }, } : { presets: never[]; automation: { mode: ""; }; }
55+
56+
presets: [],
57+
>presets : never[]
58+
>[] : never[]
59+
60+
automation: {
61+
>automation : { mode: ""; }
62+
>{ mode: "", } : { mode: ""; }
63+
64+
mode: "",
65+
>mode : ""
66+
>"" : ""
67+
68+
},
69+
} as UserSettings,
70+
}
71+
}
72+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
enum AutomationMode {
5+
NONE = "",
6+
TIME = "time",
7+
SYSTEM = "system",
8+
LOCATION = "location",
9+
}
10+
11+
interface ThemePreset {
12+
id: string;
13+
}
14+
15+
interface Automation {
16+
mode: AutomationMode;
17+
}
18+
19+
interface UserSettings {
20+
presets: ThemePreset[];
21+
automation: Automation;
22+
}
23+
24+
interface ExtensionData {
25+
settings: UserSettings;
26+
}
27+
28+
export function getMockData(): ExtensionData {
29+
return {
30+
settings: {
31+
presets: [],
32+
automation: {
33+
mode: "",
34+
},
35+
} as UserSettings,
36+
}
37+
}

0 commit comments

Comments
 (0)