mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Merge pull request #10784 from Microsoft/enum-number-assignability-in-unions
Number and enum literal are assignable to enums, even inside unions
This commit is contained in:
commit
95210acf03
@ -334,6 +334,7 @@ namespace ts {
|
||||
const assignableRelation = createMap<RelationComparisonResult>();
|
||||
const comparableRelation = createMap<RelationComparisonResult>();
|
||||
const identityRelation = createMap<RelationComparisonResult>();
|
||||
const enumRelation = createMap<boolean>();
|
||||
|
||||
// This is for caching the result of getSymbolDisplayBuilder. Do not access directly.
|
||||
let _displayBuilder: SymbolDisplayBuilder;
|
||||
@ -6206,8 +6207,14 @@ namespace ts {
|
||||
if (source === target) {
|
||||
return true;
|
||||
}
|
||||
if (source.symbol.name !== target.symbol.name || !(source.symbol.flags & SymbolFlags.RegularEnum) || !(target.symbol.flags & SymbolFlags.RegularEnum)) {
|
||||
return false;
|
||||
const id = source.id + "," + target.id;
|
||||
if (enumRelation[id] !== undefined) {
|
||||
return enumRelation[id];
|
||||
}
|
||||
if (source.symbol.name !== target.symbol.name ||
|
||||
!(source.symbol.flags & SymbolFlags.RegularEnum) || !(target.symbol.flags & SymbolFlags.RegularEnum) ||
|
||||
(source.flags & TypeFlags.Union) !== (target.flags & TypeFlags.Union)) {
|
||||
return enumRelation[id] = false;
|
||||
}
|
||||
const targetEnumType = getTypeOfSymbol(target.symbol);
|
||||
for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) {
|
||||
@ -6218,11 +6225,11 @@ namespace ts {
|
||||
errorReporter(Diagnostics.Property_0_is_missing_in_type_1, property.name,
|
||||
typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType));
|
||||
}
|
||||
return false;
|
||||
return enumRelation[id] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return enumRelation[id] = true;
|
||||
}
|
||||
|
||||
function isSimpleTypeRelatedTo(source: Type, target: Type, relation: Map<RelationComparisonResult>, errorReporter?: ErrorReporter) {
|
||||
@ -6237,8 +6244,18 @@ namespace ts {
|
||||
if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true;
|
||||
if (relation === assignableRelation || relation === comparableRelation) {
|
||||
if (source.flags & TypeFlags.Any) return true;
|
||||
if (source.flags & (TypeFlags.Number | TypeFlags.NumberLiteral) && target.flags & TypeFlags.Enum) return true;
|
||||
if (source.flags & TypeFlags.NumberLiteral && target.flags & TypeFlags.EnumLiteral && (<LiteralType>source).text === (<LiteralType>target).text) return true;
|
||||
if ((source.flags & TypeFlags.Number | source.flags & TypeFlags.NumberLiteral) && target.flags & TypeFlags.EnumLike) return true;
|
||||
if (source.flags & TypeFlags.EnumLiteral &&
|
||||
target.flags & TypeFlags.EnumLiteral &&
|
||||
(<LiteralType>source).text === (<LiteralType>target).text &&
|
||||
isEnumTypeRelatedTo((<EnumLiteralType>source).baseType, (<EnumLiteralType>target).baseType, errorReporter)) {
|
||||
return true;
|
||||
}
|
||||
if (source.flags & TypeFlags.EnumLiteral &&
|
||||
target.flags & TypeFlags.Enum &&
|
||||
isEnumTypeRelatedTo(<EnumType>target, (<EnumLiteralType>source).baseType, errorReporter)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
tests/cases/compiler/enumAssignmentCompat.ts(26,5): error TS2322: Type 'typeof W' is not assignable to type 'number'.
|
||||
tests/cases/compiler/enumAssignmentCompat.ts(28,5): error TS2322: Type 'W.a' is not assignable to type 'typeof W'.
|
||||
tests/cases/compiler/enumAssignmentCompat.ts(30,5): error TS2322: Type '3' is not assignable to type 'typeof W'.
|
||||
tests/cases/compiler/enumAssignmentCompat.ts(31,5): error TS2322: Type '4' is not assignable to type 'W.a'.
|
||||
tests/cases/compiler/enumAssignmentCompat.ts(32,5): error TS2322: Type 'W.a' is not assignable to type 'WStatic'.
|
||||
tests/cases/compiler/enumAssignmentCompat.ts(33,5): error TS2322: Type '5' is not assignable to type 'WStatic'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/enumAssignmentCompat.ts (6 errors) ====
|
||||
==== tests/cases/compiler/enumAssignmentCompat.ts (5 errors) ====
|
||||
module W {
|
||||
export class D { }
|
||||
}
|
||||
@ -44,8 +43,6 @@ tests/cases/compiler/enumAssignmentCompat.ts(33,5): error TS2322: Type '5' is no
|
||||
~
|
||||
!!! error TS2322: Type '3' is not assignable to type 'typeof W'.
|
||||
var e: typeof W.a = 4;
|
||||
~
|
||||
!!! error TS2322: Type '4' is not assignable to type 'W.a'.
|
||||
var f: WStatic = W.a; // error
|
||||
~
|
||||
!!! error TS2322: Type 'W.a' is not assignable to type 'WStatic'.
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
tests/cases/compiler/enumAssignmentCompat2.ts(25,5): error TS2322: Type 'typeof W' is not assignable to type 'number'.
|
||||
tests/cases/compiler/enumAssignmentCompat2.ts(27,5): error TS2322: Type 'W.a' is not assignable to type 'typeof W'.
|
||||
tests/cases/compiler/enumAssignmentCompat2.ts(29,5): error TS2322: Type '3' is not assignable to type 'typeof W'.
|
||||
tests/cases/compiler/enumAssignmentCompat2.ts(30,5): error TS2322: Type '4' is not assignable to type 'W.a'.
|
||||
tests/cases/compiler/enumAssignmentCompat2.ts(31,5): error TS2322: Type 'W.a' is not assignable to type 'WStatic'.
|
||||
tests/cases/compiler/enumAssignmentCompat2.ts(32,5): error TS2322: Type '5' is not assignable to type 'WStatic'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/enumAssignmentCompat2.ts (6 errors) ====
|
||||
==== tests/cases/compiler/enumAssignmentCompat2.ts (5 errors) ====
|
||||
enum W {
|
||||
|
||||
a, b, c,
|
||||
@ -43,8 +42,6 @@ tests/cases/compiler/enumAssignmentCompat2.ts(32,5): error TS2322: Type '5' is n
|
||||
~
|
||||
!!! error TS2322: Type '3' is not assignable to type 'typeof W'.
|
||||
var e: typeof W.a = 4;
|
||||
~
|
||||
!!! error TS2322: Type '4' is not assignable to type 'W.a'.
|
||||
var f: WStatic = W.a; // error
|
||||
~
|
||||
!!! error TS2322: Type 'W.a' is not assignable to type 'WStatic'.
|
||||
|
||||
@ -1,20 +1,18 @@
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(68,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'.
|
||||
Property 'd' is missing in type 'First.E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(68,1): error TS2324: Property 'd' is missing in type 'First.E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(70,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'.
|
||||
Property 'd' is missing in type 'First.E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(71,1): error TS2322: Type 'Nope' is not assignable to type 'E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(75,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'.
|
||||
Property 'c' is missing in type 'Ab.E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(72,1): error TS2322: Type 'Decl.E' is not assignable to type 'First.E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(75,1): error TS2324: Property 'c' is missing in type 'Ab.E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'.
|
||||
Property 'a' is missing in type 'Cd.E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(77,1): error TS2322: Type 'E' is not assignable to type 'Nope'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(78,1): error TS2322: Type 'First.E' is not assignable to type 'Decl.E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(82,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(83,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2322: Type 'Merged.E' is not assignable to type 'First.E'.
|
||||
Property 'd' is missing in type 'First.E'.
|
||||
tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2324: Property 'd' is missing in type 'First.E'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/enumAssignmentCompat3.ts (9 errors) ====
|
||||
==== tests/cases/compiler/enumAssignmentCompat3.ts (11 errors) ====
|
||||
namespace First {
|
||||
export enum E {
|
||||
a, b, c,
|
||||
@ -84,8 +82,7 @@ tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2322: Type 'Merged.
|
||||
abc = secondAbc; // ok
|
||||
abc = secondAbcd; // missing 'd'
|
||||
~~~
|
||||
!!! error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'.
|
||||
!!! error TS2322: Property 'd' is missing in type 'First.E'.
|
||||
!!! error TS2324: Property 'd' is missing in type 'First.E'.
|
||||
abc = secondAb; // ok
|
||||
abc = secondCd; // missing 'd'
|
||||
~~~
|
||||
@ -95,20 +92,22 @@ tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2322: Type 'Merged.
|
||||
~~~
|
||||
!!! error TS2322: Type 'Nope' is not assignable to type 'E'.
|
||||
abc = decl; // ok
|
||||
~~~
|
||||
!!! error TS2322: Type 'Decl.E' is not assignable to type 'First.E'.
|
||||
secondAbc = abc; // ok
|
||||
secondAbcd = abc; // ok
|
||||
secondAb = abc; // missing 'c'
|
||||
~~~~~~~~
|
||||
!!! error TS2322: Type 'First.E' is not assignable to type 'Ab.E'.
|
||||
!!! error TS2322: Property 'c' is missing in type 'Ab.E'.
|
||||
!!! error TS2324: Property 'c' is missing in type 'Ab.E'.
|
||||
secondCd = abc; // missing 'a' and 'b'
|
||||
~~~~~~~~
|
||||
!!! error TS2322: Type 'First.E' is not assignable to type 'Cd.E'.
|
||||
!!! error TS2322: Property 'a' is missing in type 'Cd.E'.
|
||||
nope = abc; // nope!
|
||||
~~~~
|
||||
!!! error TS2322: Type 'E' is not assignable to type 'Nope'.
|
||||
decl = abc; // ok
|
||||
~~~~
|
||||
!!! error TS2322: Type 'First.E' is not assignable to type 'Decl.E'.
|
||||
|
||||
// const is only assignable to itself
|
||||
k = k;
|
||||
@ -122,8 +121,7 @@ tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2322: Type 'Merged.
|
||||
// merged enums compare all their members
|
||||
abc = merged; // missing 'd'
|
||||
~~~
|
||||
!!! error TS2322: Type 'Merged.E' is not assignable to type 'First.E'.
|
||||
!!! error TS2322: Property 'd' is missing in type 'First.E'.
|
||||
!!! error TS2324: Property 'd' is missing in type 'First.E'.
|
||||
merged = abc; // ok
|
||||
abc = merged2; // ok
|
||||
merged2 = abc; // ok
|
||||
30
tests/baselines/reference/enumAssignmentCompat5.errors.txt
Normal file
30
tests/baselines/reference/enumAssignmentCompat5.errors.txt
Normal file
@ -0,0 +1,30 @@
|
||||
tests/cases/compiler/enumAssignmentCompat5.ts(20,9): error TS2535: Enum type 'Computed' has members with initializers that are not literals.
|
||||
|
||||
|
||||
==== tests/cases/compiler/enumAssignmentCompat5.ts (1 errors) ====
|
||||
enum E {
|
||||
A, B, C
|
||||
}
|
||||
enum Computed {
|
||||
A = 1 << 1,
|
||||
B = 1 << 2,
|
||||
C = 1 << 3,
|
||||
}
|
||||
let n: number;
|
||||
let e: E = n; // ok because it's too inconvenient otherwise
|
||||
e = 0; // ok, in range
|
||||
e = 4; // ok, out of range, but allowed computed enums don't have all members
|
||||
let a: E.A = 0; // ok, A === 0
|
||||
a = 2; // error, 2 !== 0
|
||||
a = n; // ok
|
||||
|
||||
let c: Computed = n; // ok
|
||||
c = n; // ok
|
||||
c = 4; // ok
|
||||
let ca: Computed.A = 1; // error, Computed.A isn't a literal type because Computed has no enum literals
|
||||
~~~~~~~~~~
|
||||
!!! error TS2535: Enum type 'Computed' has members with initializers that are not literals.
|
||||
|
||||
|
||||
|
||||
|
||||
50
tests/baselines/reference/enumAssignmentCompat5.js
Normal file
50
tests/baselines/reference/enumAssignmentCompat5.js
Normal file
@ -0,0 +1,50 @@
|
||||
//// [enumAssignmentCompat5.ts]
|
||||
enum E {
|
||||
A, B, C
|
||||
}
|
||||
enum Computed {
|
||||
A = 1 << 1,
|
||||
B = 1 << 2,
|
||||
C = 1 << 3,
|
||||
}
|
||||
let n: number;
|
||||
let e: E = n; // ok because it's too inconvenient otherwise
|
||||
e = 0; // ok, in range
|
||||
e = 4; // ok, out of range, but allowed computed enums don't have all members
|
||||
let a: E.A = 0; // ok, A === 0
|
||||
a = 2; // error, 2 !== 0
|
||||
a = n; // ok
|
||||
|
||||
let c: Computed = n; // ok
|
||||
c = n; // ok
|
||||
c = 4; // ok
|
||||
let ca: Computed.A = 1; // error, Computed.A isn't a literal type because Computed has no enum literals
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//// [enumAssignmentCompat5.js]
|
||||
var E;
|
||||
(function (E) {
|
||||
E[E["A"] = 0] = "A";
|
||||
E[E["B"] = 1] = "B";
|
||||
E[E["C"] = 2] = "C";
|
||||
})(E || (E = {}));
|
||||
var Computed;
|
||||
(function (Computed) {
|
||||
Computed[Computed["A"] = 2] = "A";
|
||||
Computed[Computed["B"] = 4] = "B";
|
||||
Computed[Computed["C"] = 8] = "C";
|
||||
})(Computed || (Computed = {}));
|
||||
var n;
|
||||
var e = n; // ok because it's too inconvenient otherwise
|
||||
e = 0; // ok, in range
|
||||
e = 4; // ok, out of range, but allowed computed enums don't have all members
|
||||
var a = 0; // ok, A === 0
|
||||
a = 2; // error, 2 !== 0
|
||||
a = n; // ok
|
||||
var c = n; // ok
|
||||
c = n; // ok
|
||||
c = 4; // ok
|
||||
var ca = 1; // error, Computed.A isn't a literal type because Computed has no enum literals
|
||||
@ -0,0 +1,44 @@
|
||||
tests/cases/compiler/enumLiteralAssignableToEnumInsideUnion.ts(24,7): error TS2322: Type 'Foo' is not assignable to type 'boolean | Foo'.
|
||||
tests/cases/compiler/enumLiteralAssignableToEnumInsideUnion.ts(25,7): error TS2322: Type 'Foo' is not assignable to type 'boolean | Foo'.
|
||||
tests/cases/compiler/enumLiteralAssignableToEnumInsideUnion.ts(26,7): error TS2322: Type 'Foo' is not assignable to type 'boolean | Foo.B'.
|
||||
tests/cases/compiler/enumLiteralAssignableToEnumInsideUnion.ts(27,7): error TS2322: Type 'Foo' is not assignable to type 'boolean | Foo.A'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/enumLiteralAssignableToEnumInsideUnion.ts (4 errors) ====
|
||||
module X {
|
||||
export enum Foo {
|
||||
A, B
|
||||
}
|
||||
}
|
||||
module Y {
|
||||
export enum Foo {
|
||||
A, B
|
||||
}
|
||||
}
|
||||
module Z {
|
||||
export enum Foo {
|
||||
A = 1 << 1,
|
||||
B = 1 << 2,
|
||||
}
|
||||
}
|
||||
module Ka {
|
||||
export enum Foo {
|
||||
A = 1 << 10,
|
||||
B = 1 << 11,
|
||||
}
|
||||
}
|
||||
const e0: X.Foo | boolean = Y.Foo.A; // ok
|
||||
const e1: X.Foo | boolean = Z.Foo.A; // not legal, Z is computed
|
||||
~~
|
||||
!!! error TS2322: Type 'Foo' is not assignable to type 'boolean | Foo'.
|
||||
const e2: X.Foo.A | X.Foo.B | boolean = Z.Foo.A; // still not legal
|
||||
~~
|
||||
!!! error TS2322: Type 'Foo' is not assignable to type 'boolean | Foo'.
|
||||
const e3: X.Foo.B | boolean = Z.Foo.A; // not legal
|
||||
~~
|
||||
!!! error TS2322: Type 'Foo' is not assignable to type 'boolean | Foo.B'.
|
||||
const e4: X.Foo.A | boolean = Z.Foo.A; // not legal either because Z.Foo is computed and Z.Foo.A is not necessarily assignable to X.Foo.A
|
||||
~~
|
||||
!!! error TS2322: Type 'Foo' is not assignable to type 'boolean | Foo.A'.
|
||||
const e5: Ka.Foo | boolean = Z.Foo.A; // ok
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
//// [enumLiteralAssignableToEnumInsideUnion.ts]
|
||||
module X {
|
||||
export enum Foo {
|
||||
A, B
|
||||
}
|
||||
}
|
||||
module Y {
|
||||
export enum Foo {
|
||||
A, B
|
||||
}
|
||||
}
|
||||
module Z {
|
||||
export enum Foo {
|
||||
A = 1 << 1,
|
||||
B = 1 << 2,
|
||||
}
|
||||
}
|
||||
module Ka {
|
||||
export enum Foo {
|
||||
A = 1 << 10,
|
||||
B = 1 << 11,
|
||||
}
|
||||
}
|
||||
const e0: X.Foo | boolean = Y.Foo.A; // ok
|
||||
const e1: X.Foo | boolean = Z.Foo.A; // not legal, Z is computed
|
||||
const e2: X.Foo.A | X.Foo.B | boolean = Z.Foo.A; // still not legal
|
||||
const e3: X.Foo.B | boolean = Z.Foo.A; // not legal
|
||||
const e4: X.Foo.A | boolean = Z.Foo.A; // not legal either because Z.Foo is computed and Z.Foo.A is not necessarily assignable to X.Foo.A
|
||||
const e5: Ka.Foo | boolean = Z.Foo.A; // ok
|
||||
|
||||
|
||||
//// [enumLiteralAssignableToEnumInsideUnion.js]
|
||||
var X;
|
||||
(function (X) {
|
||||
(function (Foo) {
|
||||
Foo[Foo["A"] = 0] = "A";
|
||||
Foo[Foo["B"] = 1] = "B";
|
||||
})(X.Foo || (X.Foo = {}));
|
||||
var Foo = X.Foo;
|
||||
})(X || (X = {}));
|
||||
var Y;
|
||||
(function (Y) {
|
||||
(function (Foo) {
|
||||
Foo[Foo["A"] = 0] = "A";
|
||||
Foo[Foo["B"] = 1] = "B";
|
||||
})(Y.Foo || (Y.Foo = {}));
|
||||
var Foo = Y.Foo;
|
||||
})(Y || (Y = {}));
|
||||
var Z;
|
||||
(function (Z) {
|
||||
(function (Foo) {
|
||||
Foo[Foo["A"] = 2] = "A";
|
||||
Foo[Foo["B"] = 4] = "B";
|
||||
})(Z.Foo || (Z.Foo = {}));
|
||||
var Foo = Z.Foo;
|
||||
})(Z || (Z = {}));
|
||||
var Ka;
|
||||
(function (Ka) {
|
||||
(function (Foo) {
|
||||
Foo[Foo["A"] = 1024] = "A";
|
||||
Foo[Foo["B"] = 2048] = "B";
|
||||
})(Ka.Foo || (Ka.Foo = {}));
|
||||
var Foo = Ka.Foo;
|
||||
})(Ka || (Ka = {}));
|
||||
var e0 = Y.Foo.A; // ok
|
||||
var e1 = Z.Foo.A; // not legal, Z is computed
|
||||
var e2 = Z.Foo.A; // still not legal
|
||||
var e3 = Z.Foo.A; // not legal
|
||||
var e4 = Z.Foo.A; // not legal either because Z.Foo is computed and Z.Foo.A is not necessarily assignable to X.Foo.A
|
||||
var e5 = Z.Foo.A; // ok
|
||||
@ -0,0 +1,14 @@
|
||||
//// [numberAssignableToEnumInsideUnion.ts]
|
||||
enum E { A, B }
|
||||
let n: number;
|
||||
let z: E | boolean = n;
|
||||
|
||||
|
||||
//// [numberAssignableToEnumInsideUnion.js]
|
||||
var E;
|
||||
(function (E) {
|
||||
E[E["A"] = 0] = "A";
|
||||
E[E["B"] = 1] = "B";
|
||||
})(E || (E = {}));
|
||||
var n;
|
||||
var z = n;
|
||||
@ -0,0 +1,14 @@
|
||||
=== tests/cases/compiler/numberAssignableToEnumInsideUnion.ts ===
|
||||
enum E { A, B }
|
||||
>E : Symbol(E, Decl(numberAssignableToEnumInsideUnion.ts, 0, 0))
|
||||
>A : Symbol(E.A, Decl(numberAssignableToEnumInsideUnion.ts, 0, 8))
|
||||
>B : Symbol(E.B, Decl(numberAssignableToEnumInsideUnion.ts, 0, 11))
|
||||
|
||||
let n: number;
|
||||
>n : Symbol(n, Decl(numberAssignableToEnumInsideUnion.ts, 1, 3))
|
||||
|
||||
let z: E | boolean = n;
|
||||
>z : Symbol(z, Decl(numberAssignableToEnumInsideUnion.ts, 2, 3))
|
||||
>E : Symbol(E, Decl(numberAssignableToEnumInsideUnion.ts, 0, 0))
|
||||
>n : Symbol(n, Decl(numberAssignableToEnumInsideUnion.ts, 1, 3))
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
=== tests/cases/compiler/numberAssignableToEnumInsideUnion.ts ===
|
||||
enum E { A, B }
|
||||
>E : E
|
||||
>A : E.A
|
||||
>B : E.B
|
||||
|
||||
let n: number;
|
||||
>n : number
|
||||
|
||||
let z: E | boolean = n;
|
||||
>z : boolean | E
|
||||
>E : E
|
||||
>n : number
|
||||
|
||||
23
tests/cases/compiler/enumAssignmentCompat5.ts
Normal file
23
tests/cases/compiler/enumAssignmentCompat5.ts
Normal file
@ -0,0 +1,23 @@
|
||||
enum E {
|
||||
A, B, C
|
||||
}
|
||||
enum Computed {
|
||||
A = 1 << 1,
|
||||
B = 1 << 2,
|
||||
C = 1 << 3,
|
||||
}
|
||||
let n: number;
|
||||
let e: E = n; // ok because it's too inconvenient otherwise
|
||||
e = 0; // ok, in range
|
||||
e = 4; // ok, out of range, but allowed computed enums don't have all members
|
||||
let a: E.A = 0; // ok, A === 0
|
||||
a = 2; // error, 2 !== 0
|
||||
a = n; // ok
|
||||
|
||||
let c: Computed = n; // ok
|
||||
c = n; // ok
|
||||
c = 4; // ok
|
||||
let ca: Computed.A = 1; // error, Computed.A isn't a literal type because Computed has no enum literals
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
module X {
|
||||
export enum Foo {
|
||||
A, B
|
||||
}
|
||||
}
|
||||
module Y {
|
||||
export enum Foo {
|
||||
A, B
|
||||
}
|
||||
}
|
||||
module Z {
|
||||
export enum Foo {
|
||||
A = 1 << 1,
|
||||
B = 1 << 2,
|
||||
}
|
||||
}
|
||||
module Ka {
|
||||
export enum Foo {
|
||||
A = 1 << 10,
|
||||
B = 1 << 11,
|
||||
}
|
||||
}
|
||||
const e0: X.Foo | boolean = Y.Foo.A; // ok
|
||||
const e1: X.Foo | boolean = Z.Foo.A; // not legal, Z is computed
|
||||
const e2: X.Foo.A | X.Foo.B | boolean = Z.Foo.A; // still not legal
|
||||
const e3: X.Foo.B | boolean = Z.Foo.A; // not legal
|
||||
const e4: X.Foo.A | boolean = Z.Foo.A; // not legal either because Z.Foo is computed and Z.Foo.A is not necessarily assignable to X.Foo.A
|
||||
const e5: Ka.Foo | boolean = Z.Foo.A; // ok
|
||||
@ -0,0 +1,3 @@
|
||||
enum E { A, B }
|
||||
let n: number;
|
||||
let z: E | boolean = n;
|
||||
Loading…
x
Reference in New Issue
Block a user