From 6cd5a4dac9599122eff78d016a82ac0d362850ab Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 11:03:45 -0800 Subject: [PATCH 01/13] Compare enums semi-structurally. 1. Unqualified names must match. 2. Target contains members with same names as all source members. --- src/compiler/checker.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 50a3aee9955..0f04daf2983 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5040,6 +5040,11 @@ namespace ts { if (source === undefinedType) return Ternary.True; if (source === nullType && target !== undefinedType) return Ternary.True; if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True; + if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) { + if (result = enumRelatedTo(source, target)) { + return result; + } + } if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True; if (relation === assignableRelation) { if (isTypeAny(source)) return Ternary.True; @@ -5750,6 +5755,25 @@ namespace ts { } return Ternary.False; } + + function enumRelatedTo(source: Type, target: Type) { + if (source.symbol.name !== target.symbol.name) { + return Ternary.False; + } + const sourceDecl = getMergedSymbol(source.symbol).valueDeclaration; + const targetDecl = getMergedSymbol(target.symbol).valueDeclaration; + const targetMembers = arrayToMap(targetDecl.members, member => getTextOfPropertyName(member.name)); + for (const member of sourceDecl.members) { + const name = getTextOfPropertyName(member.name); + if (!targetMembers[name]) { + reportError(Diagnostics.Property_0_is_missing_in_type_1, + name, + typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); + return Ternary.False; + } + } + return Ternary.True; + } } // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case From 6ed5b59f751f57532e43cbc0ac71ff097bcc899b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 11:05:25 -0800 Subject: [PATCH 02/13] Add test case and accept baseline --- .../enumAssignmentCompat3.errors.txt | 75 ++++++++++++ .../reference/enumAssignmentCompat3.js | 115 ++++++++++++++++++ tests/cases/compiler/enumAssignmentCompat3.ts | 45 +++++++ 3 files changed, 235 insertions(+) create mode 100644 tests/baselines/reference/enumAssignmentCompat3.errors.txt create mode 100644 tests/baselines/reference/enumAssignmentCompat3.js create mode 100644 tests/cases/compiler/enumAssignmentCompat3.ts diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt new file mode 100644 index 00000000000..d82a4b7d490 --- /dev/null +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -0,0 +1,75 @@ +tests/cases/compiler/enumAssignmentCompat3.ts(37,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(39,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(40,1): error TS2322: Type 'Nope' is not assignable to type 'E'. +tests/cases/compiler/enumAssignmentCompat3.ts(43,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(44,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(45,1): error TS2322: Type 'E' is not assignable to type 'Nope'. + + +==== tests/cases/compiler/enumAssignmentCompat3.ts (6 errors) ==== + namespace First { + export enum E { + a, b, c, + } + } + namespace Abc { + export enum E { + a, b, c, + } + export enum Nope { + a, b, c, + } + } + namespace Abcd { + export enum E { + a, b, c, d, + } + } + namespace Ab { + export enum E { + a, b, + } + } + namespace Cd { + export enum E { + c, d, + } + } + + var abc: First.E; + var secondAbc: Abc.E; + var secondAbcd: Abcd.E; + var secondAb: Ab.E; + var secondCd: Cd.E; + var nope: Abc.Nope; + 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'. + abc = secondAb; // ok + abc = secondCd; // missing 'd' + ~~~ +!!! error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. +!!! error TS2322: Property 'd' is missing in type 'First.E'. + abc = nope; // nope! + ~~~ +!!! error TS2322: Type 'Nope' is not assignable to type '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'. + 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'. + \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js new file mode 100644 index 00000000000..33cfdd28e88 --- /dev/null +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -0,0 +1,115 @@ +//// [enumAssignmentCompat3.ts] +namespace First { + export enum E { + a, b, c, + } +} +namespace Abc { + export enum E { + a, b, c, + } + export enum Nope { + a, b, c, + } +} +namespace Abcd { + export enum E { + a, b, c, d, + } +} +namespace Ab { + export enum E { + a, b, + } +} +namespace Cd { + export enum E { + c, d, + } +} + +var abc: First.E; +var secondAbc: Abc.E; +var secondAbcd: Abcd.E; +var secondAb: Ab.E; +var secondCd: Cd.E; +var nope: Abc.Nope; +abc = secondAbc; // ok +abc = secondAbcd; // missing 'd' +abc = secondAb; // ok +abc = secondCd; // missing 'd' +abc = nope; // nope! +secondAbc = abc; // ok +secondAbcd = abc; // ok +secondAb = abc; // missing 'c' +secondCd = abc; // missing 'a' and 'b' +nope = abc; // nope! + + +//// [enumAssignmentCompat3.js] +var First; +(function (First) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + })(First.E || (First.E = {})); + var E = First.E; +})(First || (First = {})); +var Abc; +(function (Abc) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + })(Abc.E || (Abc.E = {})); + var E = Abc.E; + (function (Nope) { + Nope[Nope["a"] = 0] = "a"; + Nope[Nope["b"] = 1] = "b"; + Nope[Nope["c"] = 2] = "c"; + })(Abc.Nope || (Abc.Nope = {})); + var Nope = Abc.Nope; +})(Abc || (Abc = {})); +var Abcd; +(function (Abcd) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + E[E["d"] = 3] = "d"; + })(Abcd.E || (Abcd.E = {})); + var E = Abcd.E; +})(Abcd || (Abcd = {})); +var Ab; +(function (Ab) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + })(Ab.E || (Ab.E = {})); + var E = Ab.E; +})(Ab || (Ab = {})); +var Cd; +(function (Cd) { + (function (E) { + E[E["c"] = 0] = "c"; + E[E["d"] = 1] = "d"; + })(Cd.E || (Cd.E = {})); + var E = Cd.E; +})(Cd || (Cd = {})); +var abc; +var secondAbc; +var secondAbcd; +var secondAb; +var secondCd; +var nope; +abc = secondAbc; // ok +abc = secondAbcd; // missing 'd' +abc = secondAb; // ok +abc = secondCd; // missing 'd' +abc = nope; // nope! +secondAbc = abc; // ok +secondAbcd = abc; // ok +secondAb = abc; // missing 'c' +secondCd = abc; // missing 'a' and 'b' +nope = abc; // nope! diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts new file mode 100644 index 00000000000..94a22c7f346 --- /dev/null +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -0,0 +1,45 @@ +namespace First { + export enum E { + a, b, c, + } +} +namespace Abc { + export enum E { + a, b, c, + } + export enum Nope { + a, b, c, + } +} +namespace Abcd { + export enum E { + a, b, c, d, + } +} +namespace Ab { + export enum E { + a, b, + } +} +namespace Cd { + export enum E { + c, d, + } +} + +var abc: First.E; +var secondAbc: Abc.E; +var secondAbcd: Abcd.E; +var secondAb: Ab.E; +var secondCd: Cd.E; +var nope: Abc.Nope; +abc = secondAbc; // ok +abc = secondAbcd; // missing 'd' +abc = secondAb; // ok +abc = secondCd; // missing 'd' +abc = nope; // nope! +secondAbc = abc; // ok +secondAbcd = abc; // ok +secondAb = abc; // missing 'c' +secondCd = abc; // missing 'a' and 'b' +nope = abc; // nope! From cc1d8cf395eebdf5e1f6e2f9ddb90111fbad95b7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 13:47:18 -0800 Subject: [PATCH 03/13] Address review comments --- src/compiler/checker.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0f04daf2983..857fa97ca06 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5757,15 +5757,17 @@ namespace ts { } function enumRelatedTo(source: Type, target: Type) { - if (source.symbol.name !== target.symbol.name) { + if (source.symbol.name !== target.symbol.name || + source.symbol.flags & SymbolFlags.ConstEnum || + target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const sourceDecl = getMergedSymbol(source.symbol).valueDeclaration; - const targetDecl = getMergedSymbol(target.symbol).valueDeclaration; + const sourceDecl = getDeclarationOfKind(source.symbol, SyntaxKind.EnumDeclaration); + const targetDecl = getDeclarationOfKind(target.symbol, SyntaxKind.EnumDeclaration); const targetMembers = arrayToMap(targetDecl.members, member => getTextOfPropertyName(member.name)); for (const member of sourceDecl.members) { const name = getTextOfPropertyName(member.name); - if (!targetMembers[name]) { + if (!hasProperty(targetMembers, name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, name, typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); From ff0138878ddbe5823df3d37073e875758f23ec18 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 13:47:31 -0800 Subject: [PATCH 04/13] Add tests from review --- .../enumAssignmentCompat3.errors.txt | 38 +++++++++++++++---- .../reference/enumAssignmentCompat3.js | 28 ++++++++++++++ tests/cases/compiler/enumAssignmentCompat3.ts | 18 +++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt index d82a4b7d490..b9ab92adec1 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -1,16 +1,18 @@ -tests/cases/compiler/enumAssignmentCompat3.ts(37,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(49,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(39,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(51,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(40,1): error TS2322: Type 'Nope' is not assignable to type 'E'. -tests/cases/compiler/enumAssignmentCompat3.ts(43,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(52,1): error TS2322: Type 'Nope' is not assignable to type 'E'. +tests/cases/compiler/enumAssignmentCompat3.ts(56,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(44,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(57,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(45,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +tests/cases/compiler/enumAssignmentCompat3.ts(58,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +tests/cases/compiler/enumAssignmentCompat3.ts(62,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. -==== tests/cases/compiler/enumAssignmentCompat3.ts (6 errors) ==== +==== tests/cases/compiler/enumAssignmentCompat3.ts (8 errors) ==== namespace First { export enum E { a, b, c, @@ -39,6 +41,16 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n c, d, } } + namespace Const { + export const enum E { + a, b, c, + } + } + namespace Decl { + export declare enum E { + a, b, c = 3, + } + } var abc: First.E; var secondAbc: Abc.E; @@ -46,6 +58,8 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n var secondAb: Ab.E; var secondCd: Cd.E; var nope: Abc.Nope; + var k: Const.E; + var decl: Decl.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' ~~~ @@ -59,6 +73,7 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n abc = nope; // nope! ~~~ !!! error TS2322: Type 'Nope' is not assignable to type 'E'. + abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' @@ -72,4 +87,13 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n nope = abc; // nope! ~~~~ !!! error TS2322: Type 'E' is not assignable to type 'Nope'. + decl = abc; // ok + + k = k; // const is only assignable to itself + abc = k; // error + ~~~ +!!! error TS2322: Type 'Const.E' is not assignable to type 'First.E'. + k = abc; + ~ +!!! error TS2322: Type 'First.E' is not assignable to type 'Const.E'. \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js index 33cfdd28e88..1173bfa1812 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.js +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -27,6 +27,16 @@ namespace Cd { c, d, } } +namespace Const { + export const enum E { + a, b, c, + } +} +namespace Decl { + export declare enum E { + a, b, c = 3, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -34,16 +44,24 @@ var secondAbcd: Abcd.E; var secondAb: Ab.E; var secondCd: Cd.E; var nope: Abc.Nope; +var k: Const.E; +var decl: Decl.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok abc = secondCd; // missing 'd' abc = nope; // nope! +abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! +decl = abc; // ok + +k = k; // const is only assignable to itself +abc = k; // error +k = abc; //// [enumAssignmentCompat3.js] @@ -97,19 +115,29 @@ var Cd; })(Cd.E || (Cd.E = {})); var E = Cd.E; })(Cd || (Cd = {})); +var Decl; +(function (Decl) { +})(Decl || (Decl = {})); var abc; var secondAbc; var secondAbcd; var secondAb; var secondCd; var nope; +var k; +var decl; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok abc = secondCd; // missing 'd' abc = nope; // nope! +abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! +decl = abc; // ok +k = k; // const is only assignable to itself +abc = k; // error +k = abc; diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts index 94a22c7f346..aaaf96b69c8 100644 --- a/tests/cases/compiler/enumAssignmentCompat3.ts +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -26,6 +26,16 @@ namespace Cd { c, d, } } +namespace Const { + export const enum E { + a, b, c, + } +} +namespace Decl { + export declare enum E { + a, b, c = 3, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -33,13 +43,21 @@ var secondAbcd: Abcd.E; var secondAb: Ab.E; var secondCd: Cd.E; var nope: Abc.Nope; +var k: Const.E; +var decl: Decl.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok abc = secondCd; // missing 'd' abc = nope; // nope! +abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! +decl = abc; // ok + +k = k; // const is only assignable to itself +abc = k; // error +k = abc; From a995b23e4a00e252de81cdf0d1685700314eefa6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 14:28:29 -0800 Subject: [PATCH 05/13] Handle merged enums --- src/compiler/checker.ts | 23 ++++++++++++++++++----- src/compiler/utilities.ts | 15 +++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 857fa97ca06..2fb0296c1c7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,12 +5762,11 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const sourceDecl = getDeclarationOfKind(source.symbol, SyntaxKind.EnumDeclaration); - const targetDecl = getDeclarationOfKind(target.symbol, SyntaxKind.EnumDeclaration); - const targetMembers = arrayToMap(targetDecl.members, member => getTextOfPropertyName(member.name)); - for (const member of sourceDecl.members) { + const targetMembers = getEnumMembers(target.symbol); + const targetNames = arrayToMap(targetMembers, member => getTextOfPropertyName(member.name)); + for (const member of getEnumMembers(source.symbol)) { const name = getTextOfPropertyName(member.name); - if (!hasProperty(targetMembers, name)) { + if (!hasProperty(targetNames, name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, name, typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); @@ -5778,6 +5777,20 @@ namespace ts { } } + function getEnumMembers(symbol: Symbol): EnumMember[] { + const declarations = getDeclarationsOfKind(symbol, SyntaxKind.EnumDeclaration); + if (!declarations) { + return emptyArray; + } + const members: EnumMember[] = []; + for (const declaration of declarations) { + for (const member of (declaration).members) { + members.push(member); + } + } + return members; + } + // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case // when structural type comparisons have been started for 10 or more instantiations of the same generic type. It is possible, // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely expanding. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 95bf4ff7fa3..24e2149ab3e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -27,6 +27,21 @@ namespace ts { return undefined; } + export function getDeclarationsOfKind(symbol: Symbol, kind: SyntaxKind): Declaration[] { + const declarations = symbol.declarations; + if (declarations) { + const declarationsOfKind: Declaration[] = []; + for (const declaration of declarations) { + if (declaration.kind === kind) { + declarationsOfKind.push(declaration); + } + } + return declarationsOfKind; + } + + return undefined; + } + export interface StringSymbolWriter extends SymbolWriter { string(): string; } From 75304096959652551cdeed4140753f44940e45b6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 14:28:46 -0800 Subject: [PATCH 06/13] Add merged enum test --- .../enumAssignmentCompat3.errors.txt | 40 ++++++++++++++----- .../reference/enumAssignmentCompat3.js | 37 +++++++++++++++-- tests/cases/compiler/enumAssignmentCompat3.ts | 16 +++++++- 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt index b9ab92adec1..c34ad434347 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -1,18 +1,20 @@ -tests/cases/compiler/enumAssignmentCompat3.ts(49,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(58,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(51,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(60,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(52,1): error TS2322: Type 'Nope' is not assignable to type 'E'. -tests/cases/compiler/enumAssignmentCompat3.ts(56,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(61,1): error TS2322: Type 'Nope' is not assignable to type 'E'. +tests/cases/compiler/enumAssignmentCompat3.ts(65,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(57,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(66,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(58,1): error TS2322: Type 'E' is not assignable to type 'Nope'. -tests/cases/compiler/enumAssignmentCompat3.ts(62,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(67,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +tests/cases/compiler/enumAssignmentCompat3.ts(72,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(73,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(76,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 (8 errors) ==== +==== tests/cases/compiler/enumAssignmentCompat3.ts (9 errors) ==== namespace First { export enum E { a, b, c, @@ -51,6 +53,14 @@ tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E a, b, c = 3, } } + namespace Merged { + export enum E { + a, b, + } + export enum E { + c = 3, d, + } + } var abc: First.E; var secondAbc: Abc.E; @@ -60,6 +70,7 @@ tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; + var merged: Merged.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' ~~~ @@ -89,11 +100,18 @@ tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E !!! error TS2322: Type 'E' is not assignable to type 'Nope'. decl = abc; // ok - k = k; // const is only assignable to itself + // const is only assignable to itself + k = k; abc = k; // error ~~~ !!! error TS2322: Type 'Const.E' is not assignable to type 'First.E'. k = abc; ~ !!! error TS2322: Type 'First.E' is not assignable to type 'Const.E'. - \ No newline at end of file + + // 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'. + merged = abc; // ok \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js index 1173bfa1812..e43874911ce 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.js +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -37,6 +37,14 @@ namespace Decl { a, b, c = 3, } } +namespace Merged { + export enum E { + a, b, + } + export enum E { + c = 3, d, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -46,6 +54,7 @@ var secondCd: Cd.E; var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; +var merged: Merged.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -59,10 +68,14 @@ secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! decl = abc; // ok -k = k; // const is only assignable to itself +// const is only assignable to itself +k = k; abc = k; // error k = abc; - + +// merged enums compare all their members +abc = merged; // missing 'd' +merged = abc; // ok //// [enumAssignmentCompat3.js] var First; @@ -118,6 +131,19 @@ var Cd; var Decl; (function (Decl) { })(Decl || (Decl = {})); +var Merged; +(function (Merged) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + })(Merged.E || (Merged.E = {})); + var E = Merged.E; + (function (E) { + E[E["c"] = 3] = "c"; + E[E["d"] = 4] = "d"; + })(Merged.E || (Merged.E = {})); + var E = Merged.E; +})(Merged || (Merged = {})); var abc; var secondAbc; var secondAbcd; @@ -126,6 +152,7 @@ var secondCd; var nope; var k; var decl; +var merged; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -138,6 +165,10 @@ secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! decl = abc; // ok -k = k; // const is only assignable to itself +// const is only assignable to itself +k = k; abc = k; // error k = abc; +// merged enums compare all their members +abc = merged; // missing 'd' +merged = abc; // ok diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts index aaaf96b69c8..33070572661 100644 --- a/tests/cases/compiler/enumAssignmentCompat3.ts +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -36,6 +36,14 @@ namespace Decl { a, b, c = 3, } } +namespace Merged { + export enum E { + a, b, + } + export enum E { + c = 3, d, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -45,6 +53,7 @@ var secondCd: Cd.E; var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; +var merged: Merged.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -58,6 +67,11 @@ secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! decl = abc; // ok -k = k; // const is only assignable to itself +// const is only assignable to itself +k = k; abc = k; // error k = abc; + +// merged enums compare all their members +abc = merged; // missing 'd' +merged = abc; // ok \ No newline at end of file From da8e19e191ef508d18f400db62c9297e44002da7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 15:25:01 -0800 Subject: [PATCH 07/13] Use typeof enum to resolve members. Use getTypeOfSymbol >> resolveStructuredTypeMembers >> properties instead of looking at declarations. --- src/compiler/checker.ts | 26 ++++++-------------------- src/compiler/utilities.ts | 15 --------------- 2 files changed, 6 insertions(+), 35 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2fb0296c1c7..bccbede909b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,13 +5762,13 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const targetMembers = getEnumMembers(target.symbol); - const targetNames = arrayToMap(targetMembers, member => getTextOfPropertyName(member.name)); - for (const member of getEnumMembers(source.symbol)) { - const name = getTextOfPropertyName(member.name); - if (!hasProperty(targetNames, name)) { + const sourceMembers = resolveStructuredTypeMembers(getTypeOfSymbol(source.symbol)).properties; + const targetMembers = resolveStructuredTypeMembers(getTypeOfSymbol(target.symbol)).properties; + const targetNames = arrayToMap(targetMembers, member => member.name); + for (const member of sourceMembers) { + if (!hasProperty(targetNames, member.name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, - name, + member.name, typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); return Ternary.False; } @@ -5777,20 +5777,6 @@ namespace ts { } } - function getEnumMembers(symbol: Symbol): EnumMember[] { - const declarations = getDeclarationsOfKind(symbol, SyntaxKind.EnumDeclaration); - if (!declarations) { - return emptyArray; - } - const members: EnumMember[] = []; - for (const declaration of declarations) { - for (const member of (declaration).members) { - members.push(member); - } - } - return members; - } - // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case // when structural type comparisons have been started for 10 or more instantiations of the same generic type. It is possible, // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely expanding. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 24e2149ab3e..95bf4ff7fa3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -27,21 +27,6 @@ namespace ts { return undefined; } - export function getDeclarationsOfKind(symbol: Symbol, kind: SyntaxKind): Declaration[] { - const declarations = symbol.declarations; - if (declarations) { - const declarationsOfKind: Declaration[] = []; - for (const declaration of declarations) { - if (declaration.kind === kind) { - declarationsOfKind.push(declaration); - } - } - return declarationsOfKind; - } - - return undefined; - } - export interface StringSymbolWriter extends SymbolWriter { string(): string; } From 8202576ab2d503258dbd18b7ebc1035607ebd173 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 11 Dec 2015 09:56:13 -0800 Subject: [PATCH 08/13] Filter for enum members only. --- src/compiler/checker.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bccbede909b..9944cebf54a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,10 +5762,8 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const sourceMembers = resolveStructuredTypeMembers(getTypeOfSymbol(source.symbol)).properties; - const targetMembers = resolveStructuredTypeMembers(getTypeOfSymbol(target.symbol)).properties; - const targetNames = arrayToMap(targetMembers, member => member.name); - for (const member of sourceMembers) { + const targetNames = arrayToMap(getEnumMembersOfEnumType(target), member => member.name); + for (const member of getEnumMembersOfEnumType(source)) { if (!hasProperty(targetNames, member.name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, member.name, @@ -5775,6 +5773,11 @@ namespace ts { } return Ternary.True; } + + function getEnumMembersOfEnumType(type: Type) { + return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, + property => !!(property.flags & SymbolFlags.EnumMember)); + } } // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case From dc9d307f137dc2a7b812cea42aac6927711b419a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 11 Dec 2015 10:08:01 -0800 Subject: [PATCH 09/13] Fix lint --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9944cebf54a..8d9fe1f7ba5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5775,7 +5775,7 @@ namespace ts { } function getEnumMembersOfEnumType(type: Type) { - return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, + return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, property => !!(property.flags & SymbolFlags.EnumMember)); } } From aa1a7664e73c444a5c9ecf147d85b856f94eee79 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 16 Dec 2015 12:11:24 -0800 Subject: [PATCH 10/13] Add enum/module merge test --- .../enumAssignmentCompat3.errors.txt | 32 +++++++++++++------ .../reference/enumAssignmentCompat3.js | 30 ++++++++++++++++- tests/cases/compiler/enumAssignmentCompat3.ts | 14 +++++++- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt index c34ad434347..02cb4314777 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -1,16 +1,16 @@ -tests/cases/compiler/enumAssignmentCompat3.ts(58,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +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(60,1): error TS2322: Type 'Cd.E' is not assignable to 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(61,1): error TS2322: Type 'Nope' is not assignable to type 'E'. -tests/cases/compiler/enumAssignmentCompat3.ts(65,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.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(66,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.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(67,1): error TS2322: Type 'E' is not assignable to type 'Nope'. -tests/cases/compiler/enumAssignmentCompat3.ts(72,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(73,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(77,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +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'. @@ -62,6 +62,15 @@ tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged. } } + namespace Merged2 { + export enum E { + a, b, c + } + export module E { + export let d = 5; + } + } + var abc: First.E; var secondAbc: Abc.E; var secondAbcd: Abcd.E; @@ -71,6 +80,7 @@ tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged. var k: Const.E; var decl: Decl.E; var merged: Merged.E; + var merged2: Merged2.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' ~~~ @@ -114,4 +124,6 @@ tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged. ~~~ !!! error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. !!! error TS2322: Property 'd' is missing in type 'First.E'. - merged = abc; // ok \ No newline at end of file + merged = abc; // ok + abc = merged2; // ok + merged2 = abc; // ok \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js index e43874911ce..74f74ab1652 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.js +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -46,6 +46,15 @@ namespace Merged { } } +namespace Merged2 { + export enum E { + a, b, c + } + export module E { + export let d = 5; + } +} + var abc: First.E; var secondAbc: Abc.E; var secondAbcd: Abcd.E; @@ -55,6 +64,7 @@ var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; var merged: Merged.E; +var merged2: Merged2.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -75,7 +85,9 @@ k = abc; // merged enums compare all their members abc = merged; // missing 'd' -merged = abc; // ok +merged = abc; // ok +abc = merged2; // ok +merged2 = abc; // ok //// [enumAssignmentCompat3.js] var First; @@ -144,6 +156,19 @@ var Merged; })(Merged.E || (Merged.E = {})); var E = Merged.E; })(Merged || (Merged = {})); +var Merged2; +(function (Merged2) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + })(Merged2.E || (Merged2.E = {})); + var E = Merged2.E; + var E; + (function (E) { + E.d = 5; + })(E = Merged2.E || (Merged2.E = {})); +})(Merged2 || (Merged2 = {})); var abc; var secondAbc; var secondAbcd; @@ -153,6 +178,7 @@ var nope; var k; var decl; var merged; +var merged2; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -172,3 +198,5 @@ k = abc; // merged enums compare all their members abc = merged; // missing 'd' merged = abc; // ok +abc = merged2; // ok +merged2 = abc; // ok diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts index 33070572661..97a136468e3 100644 --- a/tests/cases/compiler/enumAssignmentCompat3.ts +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -45,6 +45,15 @@ namespace Merged { } } +namespace Merged2 { + export enum E { + a, b, c + } + export module E { + export let d = 5; + } +} + var abc: First.E; var secondAbc: Abc.E; var secondAbcd: Abcd.E; @@ -54,6 +63,7 @@ var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; var merged: Merged.E; +var merged2: Merged2.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -74,4 +84,6 @@ k = abc; // merged enums compare all their members abc = merged; // missing 'd' -merged = abc; // ok \ No newline at end of file +merged = abc; // ok +abc = merged2; // ok +merged2 = abc; // ok \ No newline at end of file From 3558d7d423c6d7837c5a0e7a304ec7edcf100eb0 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 17 Dec 2015 11:34:54 -0800 Subject: [PATCH 11/13] Added README.md to 'doc' folder. --- doc/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 doc/README.md diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 00000000000..164fb69ee20 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,7 @@ +This directory contains miscellaneous documentation such as the TypeScript language specification and logo. +If you are looking for more introductory material, you might want to take a look at the [TypeScript Handbook](https://github.com/Microsoft/TypeScript-Handbook). + +# Spec Contributions + +The specification is first authored as a Microsoft Word (docx) file and then generated into Markdown and PDF formats. +Due to the binary format of docx files, and the merging difficulties that may come with it, it is preferred that any suggestions or problems found in the spec should be [filed as issues](https://github.com/Microsoft/TypeScript/issues/new) rather than sent as pull requests. \ No newline at end of file From d59831b4e86b102a28ca045ee0a61778873df1c8 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 17 Dec 2015 15:38:02 -0800 Subject: [PATCH 12/13] Get rid of list and map abstractions to reduce GC pressure --- src/compiler/checker.ts | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8d9fe1f7ba5..488549cb180 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,22 +5762,19 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const targetNames = arrayToMap(getEnumMembersOfEnumType(target), member => member.name); - for (const member of getEnumMembersOfEnumType(source)) { - if (!hasProperty(targetNames, member.name)) { - reportError(Diagnostics.Property_0_is_missing_in_type_1, - member.name, - typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); - return Ternary.False; + for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) { + if (property.flags & SymbolFlags.EnumMember) { + const targetProperty = getPropertyOfType(getTypeOfSymbol(target.symbol), property.name); + if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) { + reportError(Diagnostics.Property_0_is_missing_in_type_1, + property.name, + typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); + return Ternary.False; + } } } return Ternary.True; } - - function getEnumMembersOfEnumType(type: Type) { - return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, - property => !!(property.flags & SymbolFlags.EnumMember)); - } } // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case From b04bd66bb2a11ddfe7a7c17d35ea87ea4e9160cb Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 17 Dec 2015 16:18:55 -0800 Subject: [PATCH 13/13] Get type of target enum outside the lookup loop --- src/compiler/checker.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 488549cb180..f65a10b266a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,9 +5762,10 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } + const targetEnumType = getTypeOfSymbol(target.symbol); for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) { if (property.flags & SymbolFlags.EnumMember) { - const targetProperty = getPropertyOfType(getTypeOfSymbol(target.symbol), property.name); + const targetProperty = getPropertyOfType(targetEnumType, property.name); if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, property.name,