diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 32811dd2d661b..da60c6aed5103 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29739,7 +29739,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!hasDefaultClause) { return caseType; } - const defaultType = filterType(type, t => !(isUnitLikeType(t) && contains(switchTypes, t.flags & TypeFlags.Undefined ? undefinedType : getRegularTypeOfLiteralType(extractUnitType(t))))); + const defaultType = filterType(type, t => !(isUnitLikeType(t) && contains(switchTypes, t.flags & TypeFlags.Undefined ? undefinedType : getRegularTypeOfLiteralType(extractUnitType(t)), (t1, t2) => isUnitType(t1) && areTypesComparable(t1, t2)))); return caseType.flags & TypeFlags.Never ? defaultType : getUnionType([caseType, defaultType]); } diff --git a/tests/baselines/reference/discriminatedUnionTypes4.symbols b/tests/baselines/reference/discriminatedUnionTypes4.symbols new file mode 100644 index 0000000000000..e381263706ca8 --- /dev/null +++ b/tests/baselines/reference/discriminatedUnionTypes4.symbols @@ -0,0 +1,180 @@ +//// [tests/cases/conformance/types/union/discriminatedUnionTypes4.ts] //// + +=== discriminatedUnionTypes4.ts === +// https://github.com/microsoft/TypeScript/issues/61207 + +enum AnimalType { +>AnimalType : Symbol(AnimalType, Decl(discriminatedUnionTypes4.ts, 0, 0)) + + cat = "cat", +>cat : Symbol(AnimalType.cat, Decl(discriminatedUnionTypes4.ts, 2, 17)) + + dog = "dog", +>dog : Symbol(AnimalType.dog, Decl(discriminatedUnionTypes4.ts, 3, 14)) +} + +type Animal = +>Animal : Symbol(Animal, Decl(discriminatedUnionTypes4.ts, 5, 1)) + + | { + type: `${AnimalType.cat}`; +>type : Symbol(type, Decl(discriminatedUnionTypes4.ts, 8, 5)) +>AnimalType : Symbol(AnimalType, Decl(discriminatedUnionTypes4.ts, 0, 0)) +>cat : Symbol(AnimalType.cat, Decl(discriminatedUnionTypes4.ts, 2, 17)) + + meow: string; +>meow : Symbol(meow, Decl(discriminatedUnionTypes4.ts, 9, 32)) + } + | { + type: `${AnimalType.dog}`; +>type : Symbol(type, Decl(discriminatedUnionTypes4.ts, 12, 5)) +>AnimalType : Symbol(AnimalType, Decl(discriminatedUnionTypes4.ts, 0, 0)) +>dog : Symbol(AnimalType.dog, Decl(discriminatedUnionTypes4.ts, 3, 14)) + + bark: string; +>bark : Symbol(bark, Decl(discriminatedUnionTypes4.ts, 13, 32)) + + }; + +function check(p: never) { +>check : Symbol(check, Decl(discriminatedUnionTypes4.ts, 15, 6)) +>p : Symbol(p, Decl(discriminatedUnionTypes4.ts, 17, 15)) + + throw new Error("Error!"); +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +} + +function action1(animal: Animal) { +>action1 : Symbol(action1, Decl(discriminatedUnionTypes4.ts, 19, 1)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 21, 17)) +>Animal : Symbol(Animal, Decl(discriminatedUnionTypes4.ts, 5, 1)) + + if (animal.type === AnimalType.cat) { +>animal.type : Symbol(type, Decl(discriminatedUnionTypes4.ts, 8, 5), Decl(discriminatedUnionTypes4.ts, 12, 5)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 21, 17)) +>type : Symbol(type, Decl(discriminatedUnionTypes4.ts, 8, 5), Decl(discriminatedUnionTypes4.ts, 12, 5)) +>AnimalType.cat : Symbol(AnimalType.cat, Decl(discriminatedUnionTypes4.ts, 2, 17)) +>AnimalType : Symbol(AnimalType, Decl(discriminatedUnionTypes4.ts, 0, 0)) +>cat : Symbol(AnimalType.cat, Decl(discriminatedUnionTypes4.ts, 2, 17)) + + console.log(animal.meow); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>animal.meow : Symbol(meow, Decl(discriminatedUnionTypes4.ts, 9, 32)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 21, 17)) +>meow : Symbol(meow, Decl(discriminatedUnionTypes4.ts, 9, 32)) + + } else if (animal.type === AnimalType.dog) { +>animal.type : Symbol(type, Decl(discriminatedUnionTypes4.ts, 12, 5)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 21, 17)) +>type : Symbol(type, Decl(discriminatedUnionTypes4.ts, 12, 5)) +>AnimalType.dog : Symbol(AnimalType.dog, Decl(discriminatedUnionTypes4.ts, 3, 14)) +>AnimalType : Symbol(AnimalType, Decl(discriminatedUnionTypes4.ts, 0, 0)) +>dog : Symbol(AnimalType.dog, Decl(discriminatedUnionTypes4.ts, 3, 14)) + + console.log(animal.bark); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>animal.bark : Symbol(bark, Decl(discriminatedUnionTypes4.ts, 13, 32)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 21, 17)) +>bark : Symbol(bark, Decl(discriminatedUnionTypes4.ts, 13, 32)) + + } else { + check(animal); +>check : Symbol(check, Decl(discriminatedUnionTypes4.ts, 15, 6)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 21, 17)) + } +} + +function action2(animal: Animal) { +>action2 : Symbol(action2, Decl(discriminatedUnionTypes4.ts, 29, 1)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 31, 17)) +>Animal : Symbol(Animal, Decl(discriminatedUnionTypes4.ts, 5, 1)) + + switch (animal.type) { +>animal.type : Symbol(type, Decl(discriminatedUnionTypes4.ts, 8, 5), Decl(discriminatedUnionTypes4.ts, 12, 5)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 31, 17)) +>type : Symbol(type, Decl(discriminatedUnionTypes4.ts, 8, 5), Decl(discriminatedUnionTypes4.ts, 12, 5)) + + case `${AnimalType.cat}`: +>AnimalType.cat : Symbol(AnimalType.cat, Decl(discriminatedUnionTypes4.ts, 2, 17)) +>AnimalType : Symbol(AnimalType, Decl(discriminatedUnionTypes4.ts, 0, 0)) +>cat : Symbol(AnimalType.cat, Decl(discriminatedUnionTypes4.ts, 2, 17)) + + console.log(animal.meow); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>animal.meow : Symbol(meow, Decl(discriminatedUnionTypes4.ts, 9, 32)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 31, 17)) +>meow : Symbol(meow, Decl(discriminatedUnionTypes4.ts, 9, 32)) + + break; + case `${AnimalType.dog}`: +>AnimalType.dog : Symbol(AnimalType.dog, Decl(discriminatedUnionTypes4.ts, 3, 14)) +>AnimalType : Symbol(AnimalType, Decl(discriminatedUnionTypes4.ts, 0, 0)) +>dog : Symbol(AnimalType.dog, Decl(discriminatedUnionTypes4.ts, 3, 14)) + + console.log(animal.bark); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>animal.bark : Symbol(bark, Decl(discriminatedUnionTypes4.ts, 13, 32)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 31, 17)) +>bark : Symbol(bark, Decl(discriminatedUnionTypes4.ts, 13, 32)) + + break; + default: + check(animal); +>check : Symbol(check, Decl(discriminatedUnionTypes4.ts, 15, 6)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 31, 17)) + } +} + +function action3(animal: Animal) { +>action3 : Symbol(action3, Decl(discriminatedUnionTypes4.ts, 42, 1)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 44, 17)) +>Animal : Symbol(Animal, Decl(discriminatedUnionTypes4.ts, 5, 1)) + + switch (animal.type) { +>animal.type : Symbol(type, Decl(discriminatedUnionTypes4.ts, 8, 5), Decl(discriminatedUnionTypes4.ts, 12, 5)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 44, 17)) +>type : Symbol(type, Decl(discriminatedUnionTypes4.ts, 8, 5), Decl(discriminatedUnionTypes4.ts, 12, 5)) + + case AnimalType.cat: +>AnimalType.cat : Symbol(AnimalType.cat, Decl(discriminatedUnionTypes4.ts, 2, 17)) +>AnimalType : Symbol(AnimalType, Decl(discriminatedUnionTypes4.ts, 0, 0)) +>cat : Symbol(AnimalType.cat, Decl(discriminatedUnionTypes4.ts, 2, 17)) + + console.log(animal.meow); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>animal.meow : Symbol(meow, Decl(discriminatedUnionTypes4.ts, 9, 32)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 44, 17)) +>meow : Symbol(meow, Decl(discriminatedUnionTypes4.ts, 9, 32)) + + break; + case AnimalType.dog: +>AnimalType.dog : Symbol(AnimalType.dog, Decl(discriminatedUnionTypes4.ts, 3, 14)) +>AnimalType : Symbol(AnimalType, Decl(discriminatedUnionTypes4.ts, 0, 0)) +>dog : Symbol(AnimalType.dog, Decl(discriminatedUnionTypes4.ts, 3, 14)) + + console.log(animal.bark); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>animal.bark : Symbol(bark, Decl(discriminatedUnionTypes4.ts, 13, 32)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 44, 17)) +>bark : Symbol(bark, Decl(discriminatedUnionTypes4.ts, 13, 32)) + + break; + default: + check(animal); +>check : Symbol(check, Decl(discriminatedUnionTypes4.ts, 15, 6)) +>animal : Symbol(animal, Decl(discriminatedUnionTypes4.ts, 44, 17)) + } +} + diff --git a/tests/baselines/reference/discriminatedUnionTypes4.types b/tests/baselines/reference/discriminatedUnionTypes4.types new file mode 100644 index 0000000000000..f8f6732b7513c --- /dev/null +++ b/tests/baselines/reference/discriminatedUnionTypes4.types @@ -0,0 +1,300 @@ +//// [tests/cases/conformance/types/union/discriminatedUnionTypes4.ts] //// + +=== discriminatedUnionTypes4.ts === +// https://github.com/microsoft/TypeScript/issues/61207 + +enum AnimalType { +>AnimalType : AnimalType +> : ^^^^^^^^^^ + + cat = "cat", +>cat : AnimalType.cat +> : ^^^^^^^^^^^^^^ +>"cat" : "cat" +> : ^^^^^ + + dog = "dog", +>dog : AnimalType.dog +> : ^^^^^^^^^^^^^^ +>"dog" : "dog" +> : ^^^^^ +} + +type Animal = +>Animal : Animal +> : ^^^^^^ + + | { + type: `${AnimalType.cat}`; +>type : "cat" +> : ^^^^^ +>AnimalType : any +> : ^^^ + + meow: string; +>meow : string +> : ^^^^^^ + } + | { + type: `${AnimalType.dog}`; +>type : "dog" +> : ^^^^^ +>AnimalType : any +> : ^^^ + + bark: string; +>bark : string +> : ^^^^^^ + + }; + +function check(p: never) { +>check : (p: never) => void +> : ^ ^^ ^^^^^^^^^ +>p : never +> : ^^^^^ + + throw new Error("Error!"); +>new Error("Error!") : Error +> : ^^^^^ +>Error : ErrorConstructor +> : ^^^^^^^^^^^^^^^^ +>"Error!" : "Error!" +> : ^^^^^^^^ +} + +function action1(animal: Animal) { +>action1 : (animal: Animal) => void +> : ^ ^^ ^^^^^^^^^ +>animal : Animal +> : ^^^^^^ + + if (animal.type === AnimalType.cat) { +>animal.type === AnimalType.cat : boolean +> : ^^^^^^^ +>animal.type : "cat" | "dog" +> : ^^^^^^^^^^^^^ +>animal : Animal +> : ^^^^^^ +>type : "cat" | "dog" +> : ^^^^^^^^^^^^^ +>AnimalType.cat : AnimalType.cat +> : ^^^^^^^^^^^^^^ +>AnimalType : typeof AnimalType +> : ^^^^^^^^^^^^^^^^^ +>cat : AnimalType.cat +> : ^^^^^^^^^^^^^^ + + console.log(animal.meow); +>console.log(animal.meow) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>animal.meow : string +> : ^^^^^^ +>animal : { type: `${AnimalType.cat}`; meow: string; } +> : ^^^^^^^^ ^^^^^^^^ ^^^ +>meow : string +> : ^^^^^^ + + } else if (animal.type === AnimalType.dog) { +>animal.type === AnimalType.dog : boolean +> : ^^^^^^^ +>animal.type : "dog" +> : ^^^^^ +>animal : { type: `${AnimalType.dog}`; bark: string; } +> : ^^^^^^^^ ^^^^^^^^ ^^^ +>type : "dog" +> : ^^^^^ +>AnimalType.dog : AnimalType.dog +> : ^^^^^^^^^^^^^^ +>AnimalType : typeof AnimalType +> : ^^^^^^^^^^^^^^^^^ +>dog : AnimalType.dog +> : ^^^^^^^^^^^^^^ + + console.log(animal.bark); +>console.log(animal.bark) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>animal.bark : string +> : ^^^^^^ +>animal : { type: `${AnimalType.dog}`; bark: string; } +> : ^^^^^^^^ ^^^^^^^^ ^^^ +>bark : string +> : ^^^^^^ + + } else { + check(animal); +>check(animal) : void +> : ^^^^ +>check : (p: never) => void +> : ^ ^^ ^^^^^^^^^ +>animal : never +> : ^^^^^ + } +} + +function action2(animal: Animal) { +>action2 : (animal: Animal) => void +> : ^ ^^ ^^^^^^^^^ +>animal : Animal +> : ^^^^^^ + + switch (animal.type) { +>animal.type : "cat" | "dog" +> : ^^^^^^^^^^^^^ +>animal : Animal +> : ^^^^^^ +>type : "cat" | "dog" +> : ^^^^^^^^^^^^^ + + case `${AnimalType.cat}`: +>`${AnimalType.cat}` : "cat" +> : ^^^^^ +>AnimalType.cat : AnimalType.cat +> : ^^^^^^^^^^^^^^ +>AnimalType : typeof AnimalType +> : ^^^^^^^^^^^^^^^^^ +>cat : AnimalType.cat +> : ^^^^^^^^^^^^^^ + + console.log(animal.meow); +>console.log(animal.meow) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>animal.meow : string +> : ^^^^^^ +>animal : { type: `${AnimalType.cat}`; meow: string; } +> : ^^^^^^^^ ^^^^^^^^ ^^^ +>meow : string +> : ^^^^^^ + + break; + case `${AnimalType.dog}`: +>`${AnimalType.dog}` : "dog" +> : ^^^^^ +>AnimalType.dog : AnimalType.dog +> : ^^^^^^^^^^^^^^ +>AnimalType : typeof AnimalType +> : ^^^^^^^^^^^^^^^^^ +>dog : AnimalType.dog +> : ^^^^^^^^^^^^^^ + + console.log(animal.bark); +>console.log(animal.bark) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>animal.bark : string +> : ^^^^^^ +>animal : { type: `${AnimalType.dog}`; bark: string; } +> : ^^^^^^^^ ^^^^^^^^ ^^^ +>bark : string +> : ^^^^^^ + + break; + default: + check(animal); +>check(animal) : void +> : ^^^^ +>check : (p: never) => void +> : ^ ^^ ^^^^^^^^^ +>animal : never +> : ^^^^^ + } +} + +function action3(animal: Animal) { +>action3 : (animal: Animal) => void +> : ^ ^^ ^^^^^^^^^ +>animal : Animal +> : ^^^^^^ + + switch (animal.type) { +>animal.type : "cat" | "dog" +> : ^^^^^^^^^^^^^ +>animal : Animal +> : ^^^^^^ +>type : "cat" | "dog" +> : ^^^^^^^^^^^^^ + + case AnimalType.cat: +>AnimalType.cat : AnimalType.cat +> : ^^^^^^^^^^^^^^ +>AnimalType : typeof AnimalType +> : ^^^^^^^^^^^^^^^^^ +>cat : AnimalType.cat +> : ^^^^^^^^^^^^^^ + + console.log(animal.meow); +>console.log(animal.meow) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>animal.meow : string +> : ^^^^^^ +>animal : { type: `${AnimalType.cat}`; meow: string; } +> : ^^^^^^^^ ^^^^^^^^ ^^^ +>meow : string +> : ^^^^^^ + + break; + case AnimalType.dog: +>AnimalType.dog : AnimalType.dog +> : ^^^^^^^^^^^^^^ +>AnimalType : typeof AnimalType +> : ^^^^^^^^^^^^^^^^^ +>dog : AnimalType.dog +> : ^^^^^^^^^^^^^^ + + console.log(animal.bark); +>console.log(animal.bark) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>animal.bark : string +> : ^^^^^^ +>animal : { type: `${AnimalType.dog}`; bark: string; } +> : ^^^^^^^^ ^^^^^^^^ ^^^ +>bark : string +> : ^^^^^^ + + break; + default: + check(animal); +>check(animal) : void +> : ^^^^ +>check : (p: never) => void +> : ^ ^^ ^^^^^^^^^ +>animal : never +> : ^^^^^ + } +} + diff --git a/tests/cases/conformance/types/union/discriminatedUnionTypes4.ts b/tests/cases/conformance/types/union/discriminatedUnionTypes4.ts new file mode 100644 index 0000000000000..dc1e8f169815c --- /dev/null +++ b/tests/cases/conformance/types/union/discriminatedUnionTypes4.ts @@ -0,0 +1,59 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/61207 + +enum AnimalType { + cat = "cat", + dog = "dog", +} + +type Animal = + | { + type: `${AnimalType.cat}`; + meow: string; + } + | { + type: `${AnimalType.dog}`; + bark: string; + }; + +function check(p: never) { + throw new Error("Error!"); +} + +function action1(animal: Animal) { + if (animal.type === AnimalType.cat) { + console.log(animal.meow); + } else if (animal.type === AnimalType.dog) { + console.log(animal.bark); + } else { + check(animal); + } +} + +function action2(animal: Animal) { + switch (animal.type) { + case `${AnimalType.cat}`: + console.log(animal.meow); + break; + case `${AnimalType.dog}`: + console.log(animal.bark); + break; + default: + check(animal); + } +} + +function action3(animal: Animal) { + switch (animal.type) { + case AnimalType.cat: + console.log(animal.meow); + break; + case AnimalType.dog: + console.log(animal.bark); + break; + default: + check(animal); + } +}