diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 50a3aee995528..f65a10b266a60 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,27 @@ namespace ts {
                 }
                 return Ternary.False;
             }
+
+            function enumRelatedTo(source: Type, target: Type) {
+                if (source.symbol.name !== target.symbol.name ||
+                    source.symbol.flags & SymbolFlags.ConstEnum ||
+                    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(targetEnumType, 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;
+            }
         }
 
         // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case
diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt
new file mode 100644
index 0000000000000..02cb4314777f9
--- /dev/null
+++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt
@@ -0,0 +1,129 @@
+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(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(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(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 (9 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,
+        }
+    }
+    namespace Const {
+        export const enum E {
+            a, b, c,
+        }
+    }
+    namespace Decl {
+        export declare enum E {
+            a, b, c = 3,
+        }
+    }
+    namespace Merged {
+        export enum E {
+            a, b, 
+        }
+        export enum E {
+            c = 3, d,
+        }
+    }
+    
+    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;
+    var secondAb: Ab.E;
+    var secondCd: Cd.E;
+    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'
+    ~~~
+!!! 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'.
+    abc = decl; // ok
+    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'.
+    decl = abc; // ok
+    
+    // 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'.
+    
+    // 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
+    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
new file mode 100644
index 0000000000000..74f74ab165280
--- /dev/null
+++ b/tests/baselines/reference/enumAssignmentCompat3.js
@@ -0,0 +1,202 @@
+//// [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,
+    }
+}
+namespace Const {
+    export const enum E {
+        a, b, c,
+    }
+}
+namespace Decl {
+    export declare enum E {
+        a, b, c = 3,
+    }
+}
+namespace Merged {
+    export enum E {
+        a, b, 
+    }
+    export enum E {
+        c = 3, d,
+    }
+}
+
+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;
+var secondAb: Ab.E;
+var secondCd: Cd.E;
+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
+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
+
+// 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
+abc = merged2; // ok
+merged2 = abc; // ok
+
+//// [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 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 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;
+var secondAb;
+var secondCd;
+var nope;
+var k;
+var decl;
+var merged;
+var merged2;
+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
+// 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
+abc = merged2; // ok
+merged2 = abc; // ok
diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts
new file mode 100644
index 0000000000000..97a136468e3ee
--- /dev/null
+++ b/tests/cases/compiler/enumAssignmentCompat3.ts
@@ -0,0 +1,89 @@
+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,
+    }
+}
+namespace Const {
+    export const enum E {
+        a, b, c,
+    }
+}
+namespace Decl {
+    export declare enum E {
+        a, b, c = 3,
+    }
+}
+namespace Merged {
+    export enum E {
+        a, b, 
+    }
+    export enum E {
+        c = 3, d,
+    }
+}
+
+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;
+var secondAb: Ab.E;
+var secondCd: Cd.E;
+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
+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
+
+// 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
+abc = merged2; // ok
+merged2 = abc; // ok
\ No newline at end of file