Exclude enum/number compatibility rule from comparable relation (#42472)

* Exclude old number/enum literal compatibility rule from comparable relation

* Add tests

* Accept new baselines
This commit is contained in:
Anders Hejlsberg
2021-03-06 06:52:00 -08:00
committed by GitHub
parent ba56fca0bf
commit f918bd9c76
6 changed files with 373 additions and 1 deletions

View File

@@ -16923,7 +16923,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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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))
}
}

View File

@@ -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
}
}

View File

@@ -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;
}
}