diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 49c45384e6df5..8ac9aecfd13af 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16750,7 +16750,7 @@ namespace ts { // numeric enum literal type. This rule exists for backwards compatibility reasons because // bit-flag enum types sometimes look like literal enum types with numeric literal values. if (s & (TypeFlags.Number | TypeFlags.NumberLiteral) && !(s & TypeFlags.EnumLiteral) && ( - t & TypeFlags.Enum || t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true; + t & TypeFlags.Enum || relation === assignableRelation && t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true; } return false; } diff --git a/tests/baselines/reference/equalityWithEnumTypes.errors.txt b/tests/baselines/reference/equalityWithEnumTypes.errors.txt new file mode 100644 index 0000000000000..ebe0b71982717 --- /dev/null +++ b/tests/baselines/reference/equalityWithEnumTypes.errors.txt @@ -0,0 +1,51 @@ +tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts(14,9): error TS2367: This condition will always return 'true' since the types 'E1' and '0' have no overlap. +tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts(23,9): error TS2367: This condition will always return 'true' since the types 'E1' and '3' have no overlap. + + +==== tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts (2 errors) ==== + // Literal enum type + enum E1 { + a = 1, + b = 2, + } + + // Numeric enum type + enum E2 { + a = 1 << 0, + b = 1 << 1 + } + + function f1(v: E1) { + if (v !== 0) { // Error + ~~~~~~~ +!!! error TS2367: This condition will always return 'true' since the types 'E1' and '0' have no overlap. + v; + } + if (v !== 1) { + v; + } + if (v !== 2) { + v; + } + if (v !== 3) { // Error + ~~~~~~~ +!!! error TS2367: This condition will always return 'true' since the types 'E1' and '3' have no overlap. + v; + } + } + + function f2(v: E2) { + if (v !== 0) { + v; + } + if (v !== 1) { + v; + } + if (v !== 2) { + v; + } + if (v !== 3) { + v; + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/equalityWithEnumTypes.js b/tests/baselines/reference/equalityWithEnumTypes.js new file mode 100644 index 0000000000000..31e33c5bddad5 --- /dev/null +++ b/tests/baselines/reference/equalityWithEnumTypes.js @@ -0,0 +1,86 @@ +//// [equalityWithEnumTypes.ts] +// Literal enum type +enum E1 { + a = 1, + b = 2, +} + +// Numeric enum type +enum E2 { + a = 1 << 0, + b = 1 << 1 +} + +function f1(v: E1) { + if (v !== 0) { // Error + v; + } + if (v !== 1) { + v; + } + if (v !== 2) { + v; + } + if (v !== 3) { // Error + v; + } +} + +function f2(v: E2) { + if (v !== 0) { + v; + } + if (v !== 1) { + v; + } + if (v !== 2) { + v; + } + if (v !== 3) { + v; + } +} + + +//// [equalityWithEnumTypes.js] +"use strict"; +// Literal enum type +var E1; +(function (E1) { + E1[E1["a"] = 1] = "a"; + E1[E1["b"] = 2] = "b"; +})(E1 || (E1 = {})); +// Numeric enum type +var E2; +(function (E2) { + E2[E2["a"] = 1] = "a"; + E2[E2["b"] = 2] = "b"; +})(E2 || (E2 = {})); +function f1(v) { + if (v !== 0) { // Error + v; + } + if (v !== 1) { + v; + } + if (v !== 2) { + v; + } + if (v !== 3) { // Error + v; + } +} +function f2(v) { + if (v !== 0) { + v; + } + if (v !== 1) { + v; + } + if (v !== 2) { + v; + } + if (v !== 3) { + v; + } +} diff --git a/tests/baselines/reference/equalityWithEnumTypes.symbols b/tests/baselines/reference/equalityWithEnumTypes.symbols new file mode 100644 index 0000000000000..e3fe037eb2bcd --- /dev/null +++ b/tests/baselines/reference/equalityWithEnumTypes.symbols @@ -0,0 +1,85 @@ +=== tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts === +// Literal enum type +enum E1 { +>E1 : Symbol(E1, Decl(equalityWithEnumTypes.ts, 0, 0)) + + a = 1, +>a : Symbol(E1.a, Decl(equalityWithEnumTypes.ts, 1, 9)) + + b = 2, +>b : Symbol(E1.b, Decl(equalityWithEnumTypes.ts, 2, 10)) +} + +// Numeric enum type +enum E2 { +>E2 : Symbol(E2, Decl(equalityWithEnumTypes.ts, 4, 1)) + + a = 1 << 0, +>a : Symbol(E2.a, Decl(equalityWithEnumTypes.ts, 7, 9)) + + b = 1 << 1 +>b : Symbol(E2.b, Decl(equalityWithEnumTypes.ts, 8, 15)) +} + +function f1(v: E1) { +>f1 : Symbol(f1, Decl(equalityWithEnumTypes.ts, 10, 1)) +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12)) +>E1 : Symbol(E1, Decl(equalityWithEnumTypes.ts, 0, 0)) + + if (v !== 0) { // Error +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12)) + + v; +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12)) + } + if (v !== 1) { +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12)) + + v; +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12)) + } + if (v !== 2) { +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12)) + + v; +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12)) + } + if (v !== 3) { // Error +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12)) + + v; +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12)) + } +} + +function f2(v: E2) { +>f2 : Symbol(f2, Decl(equalityWithEnumTypes.ts, 25, 1)) +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12)) +>E2 : Symbol(E2, Decl(equalityWithEnumTypes.ts, 4, 1)) + + if (v !== 0) { +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12)) + + v; +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12)) + } + if (v !== 1) { +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12)) + + v; +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12)) + } + if (v !== 2) { +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12)) + + v; +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12)) + } + if (v !== 3) { +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12)) + + v; +>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12)) + } +} + diff --git a/tests/baselines/reference/equalityWithEnumTypes.types b/tests/baselines/reference/equalityWithEnumTypes.types new file mode 100644 index 0000000000000..935989418df22 --- /dev/null +++ b/tests/baselines/reference/equalityWithEnumTypes.types @@ -0,0 +1,107 @@ +=== tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts === +// Literal enum type +enum E1 { +>E1 : E1 + + a = 1, +>a : E1.a +>1 : 1 + + b = 2, +>b : E1.b +>2 : 2 +} + +// Numeric enum type +enum E2 { +>E2 : E2 + + a = 1 << 0, +>a : E2 +>1 << 0 : number +>1 : 1 +>0 : 0 + + b = 1 << 1 +>b : E2 +>1 << 1 : number +>1 : 1 +>1 : 1 +} + +function f1(v: E1) { +>f1 : (v: E1) => void +>v : E1 + + if (v !== 0) { // Error +>v !== 0 : boolean +>v : E1 +>0 : 0 + + v; +>v : E1 + } + if (v !== 1) { +>v !== 1 : boolean +>v : E1 +>1 : 1 + + v; +>v : E1.b + } + if (v !== 2) { +>v !== 2 : boolean +>v : E1 +>2 : 2 + + v; +>v : E1.a + } + if (v !== 3) { // Error +>v !== 3 : boolean +>v : E1 +>3 : 3 + + v; +>v : E1 + } +} + +function f2(v: E2) { +>f2 : (v: E2) => void +>v : E2 + + if (v !== 0) { +>v !== 0 : boolean +>v : E2 +>0 : 0 + + v; +>v : E2 + } + if (v !== 1) { +>v !== 1 : boolean +>v : E2 +>1 : 1 + + v; +>v : E2 + } + if (v !== 2) { +>v !== 2 : boolean +>v : E2 +>2 : 2 + + v; +>v : E2 + } + if (v !== 3) { +>v !== 3 : boolean +>v : E2 +>3 : 3 + + v; +>v : E2 + } +} + diff --git a/tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts b/tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts new file mode 100644 index 0000000000000..31a902049e202 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts @@ -0,0 +1,43 @@ +// @strict: true + +// Literal enum type +enum E1 { + a = 1, + b = 2, +} + +// Numeric enum type +enum E2 { + a = 1 << 0, + b = 1 << 1 +} + +function f1(v: E1) { + if (v !== 0) { // Error + v; + } + if (v !== 1) { + v; + } + if (v !== 2) { + v; + } + if (v !== 3) { // Error + v; + } +} + +function f2(v: E2) { + if (v !== 0) { + v; + } + if (v !== 1) { + v; + } + if (v !== 2) { + v; + } + if (v !== 3) { + v; + } +}