diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts
index 5ad15f4d5c461..b3e2efb494009 100644
--- a/src/compiler/binder.ts
+++ b/src/compiler/binder.ts
@@ -623,7 +623,7 @@ namespace ts {
                 case SyntaxKind.ExclamationEqualsToken:
                 case SyntaxKind.EqualsEqualsEqualsToken:
                 case SyntaxKind.ExclamationEqualsEqualsToken:
-                    if (isNarrowingExpression(expr.left) && (expr.right.kind === SyntaxKind.NullKeyword || expr.right.kind === SyntaxKind.Identifier)) {
+                    if (isNarrowingExpression(expr.left)) {
                         return true;
                     }
                     if (expr.left.kind === SyntaxKind.TypeOfExpression && isNarrowingExpression((<TypeOfExpression>expr.left).expression) && expr.right.kind === SyntaxKind.StringLiteral) {
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 6a42dc43d5159..f81b7e1d3e719 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -7698,6 +7698,103 @@ namespace ts {
                 return isMatchingReference(expr, reference) ? getTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy) : type;
             }
 
+            function narrowTypeByValueExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
+                assumeTrue = (expr.operatorToken.kind === SyntaxKind.EqualsEqualsEqualsToken || expr.operatorToken.kind === SyntaxKind.EqualsEqualsToken) ? assumeTrue : !assumeTrue;
+                let lhs = expr.left;
+                // selectors is the stack of property names used to select down into a type to get the member being narrowed
+                const selectors: string[] = [];
+                while (lhs.kind !== SyntaxKind.Identifier) {
+                    switch (lhs.kind) {
+                        case SyntaxKind.ParenthesizedExpression:
+                            lhs = (lhs as ParenthesizedExpression).expression;
+                            break;
+                        case SyntaxKind.PropertyAccessExpression:
+                            const name = (lhs as PropertyAccessExpression).name.text;
+                            // If a name doesn't resolve, bail
+                            if (name === undefined) {
+                                return type;
+                            }
+                            selectors.push(name);
+                            lhs = (lhs as PropertyAccessExpression).expression;
+                            break;
+                        case SyntaxKind.Identifier:
+                            break;
+                        default:
+                            // Unhandled control flow construct, don't narrow
+                            return type;
+                    }
+                }
+
+                if (!isMatchingReference(lhs, reference)) {
+                    return type;
+                }
+                const rhsType = checkExpressionCached(expr.right);
+
+                if (assumeTrue) {
+                    return narrowIntrospectively(type);
+                }
+                return type;
+
+                /** 
+                 * Descend into the type using the selectors we accumulated above and narrow any unions along the way
+                 * If assumeTrue, we narrow by removing all types not compatible with the rhs type
+                 * If not, we narrow only if the rhsType is a Value type (ie, StringLiteral) by removing all types compatible with that type (TODO)
+                 */
+                function narrowIntrospectively(type: Type) {
+                    const propName = selectors.pop();
+                    if (propName === undefined) {
+                        // Selected all the way into the object, return the type for the property to be narrowed
+                        if (isTypeSubtypeOf(rhsType, type)) {
+                            return rhsType;
+                        }
+                        else {
+                            return type;
+                        }
+                    }
+                    if (type.flags & TypeFlags.Union) {
+                        const reducedUnion = getUnionType(
+                            filter((type as UnionType).types, t => isMemberSubtype(t, rhsType, [...selectors, propName])),
+                            /*noSubtypeReduction*/ true
+                        );
+
+                        if (reducedUnion !== emptyUnionType) {
+                            return narrowBasedOnMatchingProperty(reducedUnion, propName);
+                        }
+                        else {
+                            return type;
+                        }
+                    }
+
+                    return narrowBasedOnMatchingProperty(type, propName);
+                }
+
+                function isMemberSubtype(type: Type, check: Type, selectors: string[]): boolean {
+                    if (!selectors.length) {
+                        return isTypeSubtypeOf(type, check);
+                    }
+                    const name = selectors.pop();
+                    const childProp = getPropertyOfType(type, name);
+                    const propType = childProp && getTypeOfSymbol(childProp);
+                    return propType && isMemberSubtype(propType, check, selectors);
+                }
+
+                function narrowBasedOnMatchingProperty(type: Type, name: string): Type {
+                    const childProp = getPropertyOfType(type, name);
+                    const propType = childProp && getTypeOfSymbol(childProp);
+                    const narrowedType = propType && narrowIntrospectively(propType);
+
+                    if (narrowedType && !isTypeIdenticalTo(propType, narrowedType)) {
+                        const symbols = cloneSymbolTable(resolveStructuredTypeMembers(type as ObjectType).members);
+                        const temp = createSymbol(childProp.flags, name);
+                        getSymbolLinks(temp).type = narrowedType;
+                        symbols[name] = temp;
+                        return createAnonymousType(createSymbol(type.symbol.flags, type.symbol.name), symbols, getSignaturesOfType(type, SignatureKind.Call),
+                            getSignaturesOfType(type, SignatureKind.Construct), getIndexInfoOfType(type, IndexKind.String), getIndexInfoOfType(type, IndexKind.Number));
+                    }
+                    return type;
+                }
+            }
+
             function narrowTypeByBinaryExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
                 switch (expr.operatorToken.kind) {
                     case SyntaxKind.EqualsToken:
@@ -7712,7 +7809,7 @@ namespace ts {
                         if (expr.left.kind === SyntaxKind.TypeOfExpression && expr.right.kind === SyntaxKind.StringLiteral) {
                             return narrowTypeByTypeof(type, expr, assumeTrue);
                         }
-                        break;
+                        return narrowTypeByValueExpression(type, expr, assumeTrue);
                     case SyntaxKind.InstanceOfKeyword:
                         return narrowTypeByInstanceof(type, expr, assumeTrue);
                     case SyntaxKind.CommaToken:
diff --git a/tests/baselines/reference/equalityWithUnionTypes01.types b/tests/baselines/reference/equalityWithUnionTypes01.types
index 61e3803094903..f61dca64eea29 100644
--- a/tests/baselines/reference/equalityWithUnionTypes01.types
+++ b/tests/baselines/reference/equalityWithUnionTypes01.types
@@ -54,17 +54,17 @@ else if (y == z || z == y) {
 >y == z || z == y : boolean
 >y == z : boolean
 >y : I2
->z : I1
+>z : I2
 >z == y : boolean
->z : I1
+>z : I2
 >y : I2
 }
 else if (y != z || z != y) {
 >y != z || z != y : boolean
 >y != z : boolean
 >y : I2
->z : I1
+>z : I2
 >z != y : boolean
->z : I1
+>z : I2
 >y : I2
 }
diff --git a/tests/baselines/reference/typeGuardByEqualityCheck.js b/tests/baselines/reference/typeGuardByEqualityCheck.js
new file mode 100644
index 0000000000000..f3125c779e53e
--- /dev/null
+++ b/tests/baselines/reference/typeGuardByEqualityCheck.js
@@ -0,0 +1,107 @@
+//// [typeGuardByEqualityCheck.ts]
+interface Discriminator {
+	_discriminator: void;
+}
+
+interface FooDiscriminator extends Discriminator {
+	_foo: void;
+}
+
+interface BarDiscriminator extends Discriminator {
+	_bar: void;
+}
+
+interface BaseNode {
+	kind: Discriminator;
+}
+
+interface FooNode extends BaseNode {
+	kind: FooDiscriminator;
+	foo: string;
+}
+
+interface BarNode extends BaseNode {
+	kind: BarDiscriminator;
+	bar: string;
+}
+
+let a: FooDiscriminator;
+let x: FooNode | BarNode;
+
+if (x.kind === a) {
+	x.foo = "yay!";
+}
+else {
+	x; // Not narrowed at present
+}
+
+let z: {
+	value: string;
+	item: FooNode | BarNode;
+}
+if (z.item.kind === a) {
+	z.item.foo = "cool!";
+	z.value = "yes";
+}
+
+let foo: "foo";
+let bar: "bar";
+let foobar: "foobar";
+
+interface Thing {
+	kind: string;
+}
+interface FooThing extends Thing {
+	kind: "foo";
+	foo: string;
+}
+interface BarThing extends Thing {
+	kind: "bar";
+	bar: string;
+}
+interface FooBarThing extends Thing {
+	kind: "foobar";
+	foo: string;
+	bar: string;
+}
+
+let gg: FooThing | BarThing | FooBarThing;
+if (gg.kind === foobar) {
+	gg.bar = "bar";
+	gg.foo = "foo";
+}
+let holder = {
+	value: gg
+};
+if (holder.value.kind === foo) {
+	holder.value.foo = "foo";
+}
+
+//// [typeGuardByEqualityCheck.js]
+var a;
+var x;
+if (x.kind === a) {
+    x.foo = "yay!";
+}
+else {
+    x; // Not narrowed at present
+}
+var z;
+if (z.item.kind === a) {
+    z.item.foo = "cool!";
+    z.value = "yes";
+}
+var foo;
+var bar;
+var foobar;
+var gg;
+if (gg.kind === foobar) {
+    gg.bar = "bar";
+    gg.foo = "foo";
+}
+var holder = {
+    value: gg
+};
+if (holder.value.kind === foo) {
+    holder.value.foo = "foo";
+}
diff --git a/tests/baselines/reference/typeGuardByEqualityCheck.symbols b/tests/baselines/reference/typeGuardByEqualityCheck.symbols
new file mode 100644
index 0000000000000..d8df9a7a0bba1
--- /dev/null
+++ b/tests/baselines/reference/typeGuardByEqualityCheck.symbols
@@ -0,0 +1,207 @@
+=== tests/cases/conformance/expressions/typeGuards/typeGuardByEqualityCheck.ts ===
+interface Discriminator {
+>Discriminator : Symbol(Discriminator, Decl(typeGuardByEqualityCheck.ts, 0, 0))
+
+	_discriminator: void;
+>_discriminator : Symbol(Discriminator._discriminator, Decl(typeGuardByEqualityCheck.ts, 0, 25))
+}
+
+interface FooDiscriminator extends Discriminator {
+>FooDiscriminator : Symbol(FooDiscriminator, Decl(typeGuardByEqualityCheck.ts, 2, 1))
+>Discriminator : Symbol(Discriminator, Decl(typeGuardByEqualityCheck.ts, 0, 0))
+
+	_foo: void;
+>_foo : Symbol(FooDiscriminator._foo, Decl(typeGuardByEqualityCheck.ts, 4, 50))
+}
+
+interface BarDiscriminator extends Discriminator {
+>BarDiscriminator : Symbol(BarDiscriminator, Decl(typeGuardByEqualityCheck.ts, 6, 1))
+>Discriminator : Symbol(Discriminator, Decl(typeGuardByEqualityCheck.ts, 0, 0))
+
+	_bar: void;
+>_bar : Symbol(BarDiscriminator._bar, Decl(typeGuardByEqualityCheck.ts, 8, 50))
+}
+
+interface BaseNode {
+>BaseNode : Symbol(BaseNode, Decl(typeGuardByEqualityCheck.ts, 10, 1))
+
+	kind: Discriminator;
+>kind : Symbol(BaseNode.kind, Decl(typeGuardByEqualityCheck.ts, 12, 20))
+>Discriminator : Symbol(Discriminator, Decl(typeGuardByEqualityCheck.ts, 0, 0))
+}
+
+interface FooNode extends BaseNode {
+>FooNode : Symbol(FooNode, Decl(typeGuardByEqualityCheck.ts, 14, 1))
+>BaseNode : Symbol(BaseNode, Decl(typeGuardByEqualityCheck.ts, 10, 1))
+
+	kind: FooDiscriminator;
+>kind : Symbol(FooNode.kind, Decl(typeGuardByEqualityCheck.ts, 16, 36))
+>FooDiscriminator : Symbol(FooDiscriminator, Decl(typeGuardByEqualityCheck.ts, 2, 1))
+
+	foo: string;
+>foo : Symbol(FooNode.foo, Decl(typeGuardByEqualityCheck.ts, 17, 24))
+}
+
+interface BarNode extends BaseNode {
+>BarNode : Symbol(BarNode, Decl(typeGuardByEqualityCheck.ts, 19, 1))
+>BaseNode : Symbol(BaseNode, Decl(typeGuardByEqualityCheck.ts, 10, 1))
+
+	kind: BarDiscriminator;
+>kind : Symbol(BarNode.kind, Decl(typeGuardByEqualityCheck.ts, 21, 36))
+>BarDiscriminator : Symbol(BarDiscriminator, Decl(typeGuardByEqualityCheck.ts, 6, 1))
+
+	bar: string;
+>bar : Symbol(BarNode.bar, Decl(typeGuardByEqualityCheck.ts, 22, 24))
+}
+
+let a: FooDiscriminator;
+>a : Symbol(a, Decl(typeGuardByEqualityCheck.ts, 26, 3))
+>FooDiscriminator : Symbol(FooDiscriminator, Decl(typeGuardByEqualityCheck.ts, 2, 1))
+
+let x: FooNode | BarNode;
+>x : Symbol(x, Decl(typeGuardByEqualityCheck.ts, 27, 3))
+>FooNode : Symbol(FooNode, Decl(typeGuardByEqualityCheck.ts, 14, 1))
+>BarNode : Symbol(BarNode, Decl(typeGuardByEqualityCheck.ts, 19, 1))
+
+if (x.kind === a) {
+>x.kind : Symbol(kind, Decl(typeGuardByEqualityCheck.ts, 16, 36), Decl(typeGuardByEqualityCheck.ts, 21, 36))
+>x : Symbol(x, Decl(typeGuardByEqualityCheck.ts, 27, 3))
+>kind : Symbol(kind, Decl(typeGuardByEqualityCheck.ts, 16, 36), Decl(typeGuardByEqualityCheck.ts, 21, 36))
+>a : Symbol(a, Decl(typeGuardByEqualityCheck.ts, 26, 3))
+
+	x.foo = "yay!";
+>x.foo : Symbol(FooNode.foo, Decl(typeGuardByEqualityCheck.ts, 17, 24))
+>x : Symbol(x, Decl(typeGuardByEqualityCheck.ts, 27, 3))
+>foo : Symbol(FooNode.foo, Decl(typeGuardByEqualityCheck.ts, 17, 24))
+}
+else {
+	x; // Not narrowed at present
+>x : Symbol(x, Decl(typeGuardByEqualityCheck.ts, 27, 3))
+}
+
+let z: {
+>z : Symbol(z, Decl(typeGuardByEqualityCheck.ts, 36, 3))
+
+	value: string;
+>value : Symbol(value, Decl(typeGuardByEqualityCheck.ts, 36, 8))
+
+	item: FooNode | BarNode;
+>item : Symbol(item, Decl(typeGuardByEqualityCheck.ts, 37, 15))
+>FooNode : Symbol(FooNode, Decl(typeGuardByEqualityCheck.ts, 14, 1))
+>BarNode : Symbol(BarNode, Decl(typeGuardByEqualityCheck.ts, 19, 1))
+}
+if (z.item.kind === a) {
+>z.item.kind : Symbol(kind, Decl(typeGuardByEqualityCheck.ts, 16, 36), Decl(typeGuardByEqualityCheck.ts, 21, 36))
+>z.item : Symbol(item, Decl(typeGuardByEqualityCheck.ts, 37, 15))
+>z : Symbol(z, Decl(typeGuardByEqualityCheck.ts, 36, 3))
+>item : Symbol(item, Decl(typeGuardByEqualityCheck.ts, 37, 15))
+>kind : Symbol(kind, Decl(typeGuardByEqualityCheck.ts, 16, 36), Decl(typeGuardByEqualityCheck.ts, 21, 36))
+>a : Symbol(a, Decl(typeGuardByEqualityCheck.ts, 26, 3))
+
+	z.item.foo = "cool!";
+>z.item.foo : Symbol(FooNode.foo, Decl(typeGuardByEqualityCheck.ts, 17, 24))
+>z.item : Symbol(item)
+>z : Symbol(z, Decl(typeGuardByEqualityCheck.ts, 36, 3))
+>item : Symbol(item)
+>foo : Symbol(FooNode.foo, Decl(typeGuardByEqualityCheck.ts, 17, 24))
+
+	z.value = "yes";
+>z.value : Symbol(value, Decl(typeGuardByEqualityCheck.ts, 36, 8))
+>z : Symbol(z, Decl(typeGuardByEqualityCheck.ts, 36, 3))
+>value : Symbol(value, Decl(typeGuardByEqualityCheck.ts, 36, 8))
+}
+
+let foo: "foo";
+>foo : Symbol(foo, Decl(typeGuardByEqualityCheck.ts, 45, 3))
+
+let bar: "bar";
+>bar : Symbol(bar, Decl(typeGuardByEqualityCheck.ts, 46, 3))
+
+let foobar: "foobar";
+>foobar : Symbol(foobar, Decl(typeGuardByEqualityCheck.ts, 47, 3))
+
+interface Thing {
+>Thing : Symbol(Thing, Decl(typeGuardByEqualityCheck.ts, 47, 21))
+
+	kind: string;
+>kind : Symbol(Thing.kind, Decl(typeGuardByEqualityCheck.ts, 49, 17))
+}
+interface FooThing extends Thing {
+>FooThing : Symbol(FooThing, Decl(typeGuardByEqualityCheck.ts, 51, 1))
+>Thing : Symbol(Thing, Decl(typeGuardByEqualityCheck.ts, 47, 21))
+
+	kind: "foo";
+>kind : Symbol(FooThing.kind, Decl(typeGuardByEqualityCheck.ts, 52, 34))
+
+	foo: string;
+>foo : Symbol(FooThing.foo, Decl(typeGuardByEqualityCheck.ts, 53, 13))
+}
+interface BarThing extends Thing {
+>BarThing : Symbol(BarThing, Decl(typeGuardByEqualityCheck.ts, 55, 1))
+>Thing : Symbol(Thing, Decl(typeGuardByEqualityCheck.ts, 47, 21))
+
+	kind: "bar";
+>kind : Symbol(BarThing.kind, Decl(typeGuardByEqualityCheck.ts, 56, 34))
+
+	bar: string;
+>bar : Symbol(BarThing.bar, Decl(typeGuardByEqualityCheck.ts, 57, 13))
+}
+interface FooBarThing extends Thing {
+>FooBarThing : Symbol(FooBarThing, Decl(typeGuardByEqualityCheck.ts, 59, 1))
+>Thing : Symbol(Thing, Decl(typeGuardByEqualityCheck.ts, 47, 21))
+
+	kind: "foobar";
+>kind : Symbol(FooBarThing.kind, Decl(typeGuardByEqualityCheck.ts, 60, 37))
+
+	foo: string;
+>foo : Symbol(FooBarThing.foo, Decl(typeGuardByEqualityCheck.ts, 61, 16))
+
+	bar: string;
+>bar : Symbol(FooBarThing.bar, Decl(typeGuardByEqualityCheck.ts, 62, 13))
+}
+
+let gg: FooThing | BarThing | FooBarThing;
+>gg : Symbol(gg, Decl(typeGuardByEqualityCheck.ts, 66, 3))
+>FooThing : Symbol(FooThing, Decl(typeGuardByEqualityCheck.ts, 51, 1))
+>BarThing : Symbol(BarThing, Decl(typeGuardByEqualityCheck.ts, 55, 1))
+>FooBarThing : Symbol(FooBarThing, Decl(typeGuardByEqualityCheck.ts, 59, 1))
+
+if (gg.kind === foobar) {
+>gg.kind : Symbol(kind, Decl(typeGuardByEqualityCheck.ts, 52, 34), Decl(typeGuardByEqualityCheck.ts, 56, 34), Decl(typeGuardByEqualityCheck.ts, 60, 37))
+>gg : Symbol(gg, Decl(typeGuardByEqualityCheck.ts, 66, 3))
+>kind : Symbol(kind, Decl(typeGuardByEqualityCheck.ts, 52, 34), Decl(typeGuardByEqualityCheck.ts, 56, 34), Decl(typeGuardByEqualityCheck.ts, 60, 37))
+>foobar : Symbol(foobar, Decl(typeGuardByEqualityCheck.ts, 47, 3))
+
+	gg.bar = "bar";
+>gg.bar : Symbol(FooBarThing.bar, Decl(typeGuardByEqualityCheck.ts, 62, 13))
+>gg : Symbol(gg, Decl(typeGuardByEqualityCheck.ts, 66, 3))
+>bar : Symbol(FooBarThing.bar, Decl(typeGuardByEqualityCheck.ts, 62, 13))
+
+	gg.foo = "foo";
+>gg.foo : Symbol(FooBarThing.foo, Decl(typeGuardByEqualityCheck.ts, 61, 16))
+>gg : Symbol(gg, Decl(typeGuardByEqualityCheck.ts, 66, 3))
+>foo : Symbol(FooBarThing.foo, Decl(typeGuardByEqualityCheck.ts, 61, 16))
+}
+let holder = {
+>holder : Symbol(holder, Decl(typeGuardByEqualityCheck.ts, 71, 3))
+
+	value: gg
+>value : Symbol(value, Decl(typeGuardByEqualityCheck.ts, 71, 14))
+>gg : Symbol(gg, Decl(typeGuardByEqualityCheck.ts, 66, 3))
+
+};
+if (holder.value.kind === foo) {
+>holder.value.kind : Symbol(kind, Decl(typeGuardByEqualityCheck.ts, 52, 34), Decl(typeGuardByEqualityCheck.ts, 56, 34), Decl(typeGuardByEqualityCheck.ts, 60, 37))
+>holder.value : Symbol(value, Decl(typeGuardByEqualityCheck.ts, 71, 14))
+>holder : Symbol(holder, Decl(typeGuardByEqualityCheck.ts, 71, 3))
+>value : Symbol(value, Decl(typeGuardByEqualityCheck.ts, 71, 14))
+>kind : Symbol(kind, Decl(typeGuardByEqualityCheck.ts, 52, 34), Decl(typeGuardByEqualityCheck.ts, 56, 34), Decl(typeGuardByEqualityCheck.ts, 60, 37))
+>foo : Symbol(foo, Decl(typeGuardByEqualityCheck.ts, 45, 3))
+
+	holder.value.foo = "foo";
+>holder.value.foo : Symbol(FooThing.foo, Decl(typeGuardByEqualityCheck.ts, 53, 13))
+>holder.value : Symbol(value)
+>holder : Symbol(holder, Decl(typeGuardByEqualityCheck.ts, 71, 3))
+>value : Symbol(value)
+>foo : Symbol(FooThing.foo, Decl(typeGuardByEqualityCheck.ts, 53, 13))
+}
diff --git a/tests/baselines/reference/typeGuardByEqualityCheck.types b/tests/baselines/reference/typeGuardByEqualityCheck.types
new file mode 100644
index 0000000000000..0fa6bf0efcc42
--- /dev/null
+++ b/tests/baselines/reference/typeGuardByEqualityCheck.types
@@ -0,0 +1,224 @@
+=== tests/cases/conformance/expressions/typeGuards/typeGuardByEqualityCheck.ts ===
+interface Discriminator {
+>Discriminator : Discriminator
+
+	_discriminator: void;
+>_discriminator : void
+}
+
+interface FooDiscriminator extends Discriminator {
+>FooDiscriminator : FooDiscriminator
+>Discriminator : Discriminator
+
+	_foo: void;
+>_foo : void
+}
+
+interface BarDiscriminator extends Discriminator {
+>BarDiscriminator : BarDiscriminator
+>Discriminator : Discriminator
+
+	_bar: void;
+>_bar : void
+}
+
+interface BaseNode {
+>BaseNode : BaseNode
+
+	kind: Discriminator;
+>kind : Discriminator
+>Discriminator : Discriminator
+}
+
+interface FooNode extends BaseNode {
+>FooNode : FooNode
+>BaseNode : BaseNode
+
+	kind: FooDiscriminator;
+>kind : FooDiscriminator
+>FooDiscriminator : FooDiscriminator
+
+	foo: string;
+>foo : string
+}
+
+interface BarNode extends BaseNode {
+>BarNode : BarNode
+>BaseNode : BaseNode
+
+	kind: BarDiscriminator;
+>kind : BarDiscriminator
+>BarDiscriminator : BarDiscriminator
+
+	bar: string;
+>bar : string
+}
+
+let a: FooDiscriminator;
+>a : FooDiscriminator
+>FooDiscriminator : FooDiscriminator
+
+let x: FooNode | BarNode;
+>x : FooNode | BarNode
+>FooNode : FooNode
+>BarNode : BarNode
+
+if (x.kind === a) {
+>x.kind === a : boolean
+>x.kind : FooDiscriminator | BarDiscriminator
+>x : FooNode | BarNode
+>kind : FooDiscriminator | BarDiscriminator
+>a : FooDiscriminator
+
+	x.foo = "yay!";
+>x.foo = "yay!" : string
+>x.foo : string
+>x : FooNode
+>foo : string
+>"yay!" : string
+}
+else {
+	x; // Not narrowed at present
+>x : FooNode | BarNode
+}
+
+let z: {
+>z : { value: string; item: FooNode | BarNode; }
+
+	value: string;
+>value : string
+
+	item: FooNode | BarNode;
+>item : FooNode | BarNode
+>FooNode : FooNode
+>BarNode : BarNode
+}
+if (z.item.kind === a) {
+>z.item.kind === a : boolean
+>z.item.kind : FooDiscriminator | BarDiscriminator
+>z.item : FooNode | BarNode
+>z : { value: string; item: FooNode | BarNode; }
+>item : FooNode | BarNode
+>kind : FooDiscriminator | BarDiscriminator
+>a : FooDiscriminator
+
+	z.item.foo = "cool!";
+>z.item.foo = "cool!" : string
+>z.item.foo : string
+>z.item : FooNode
+>z : { value: string; item: FooNode; }
+>item : FooNode
+>foo : string
+>"cool!" : string
+
+	z.value = "yes";
+>z.value = "yes" : string
+>z.value : string
+>z : { value: string; item: FooNode; }
+>value : string
+>"yes" : string
+}
+
+let foo: "foo";
+>foo : "foo"
+
+let bar: "bar";
+>bar : "bar"
+
+let foobar: "foobar";
+>foobar : "foobar"
+
+interface Thing {
+>Thing : Thing
+
+	kind: string;
+>kind : string
+}
+interface FooThing extends Thing {
+>FooThing : FooThing
+>Thing : Thing
+
+	kind: "foo";
+>kind : "foo"
+
+	foo: string;
+>foo : string
+}
+interface BarThing extends Thing {
+>BarThing : BarThing
+>Thing : Thing
+
+	kind: "bar";
+>kind : "bar"
+
+	bar: string;
+>bar : string
+}
+interface FooBarThing extends Thing {
+>FooBarThing : FooBarThing
+>Thing : Thing
+
+	kind: "foobar";
+>kind : "foobar"
+
+	foo: string;
+>foo : string
+
+	bar: string;
+>bar : string
+}
+
+let gg: FooThing | BarThing | FooBarThing;
+>gg : FooThing | BarThing | FooBarThing
+>FooThing : FooThing
+>BarThing : BarThing
+>FooBarThing : FooBarThing
+
+if (gg.kind === foobar) {
+>gg.kind === foobar : boolean
+>gg.kind : "foo" | "bar" | "foobar"
+>gg : FooThing | BarThing | FooBarThing
+>kind : "foo" | "bar" | "foobar"
+>foobar : "foobar"
+
+	gg.bar = "bar";
+>gg.bar = "bar" : string
+>gg.bar : string
+>gg : FooBarThing
+>bar : string
+>"bar" : string
+
+	gg.foo = "foo";
+>gg.foo = "foo" : string
+>gg.foo : string
+>gg : FooBarThing
+>foo : string
+>"foo" : string
+}
+let holder = {
+>holder : { value: FooThing | BarThing | FooBarThing; }
+>{	value: gg} : { value: FooThing | BarThing | FooBarThing; }
+
+	value: gg
+>value : FooThing | BarThing | FooBarThing
+>gg : FooThing | BarThing | FooBarThing
+
+};
+if (holder.value.kind === foo) {
+>holder.value.kind === foo : boolean
+>holder.value.kind : "foo" | "bar" | "foobar"
+>holder.value : FooThing | BarThing | FooBarThing
+>holder : { value: FooThing | BarThing | FooBarThing; }
+>value : FooThing | BarThing | FooBarThing
+>kind : "foo" | "bar" | "foobar"
+>foo : "foo"
+
+	holder.value.foo = "foo";
+>holder.value.foo = "foo" : string
+>holder.value.foo : string
+>holder.value : FooThing
+>holder : { value: FooThing; }
+>value : FooThing
+>foo : string
+>"foo" : string
+}
diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardByEqualityCheck.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardByEqualityCheck.ts
new file mode 100644
index 0000000000000..ac158c3806153
--- /dev/null
+++ b/tests/cases/conformance/expressions/typeGuards/typeGuardByEqualityCheck.ts
@@ -0,0 +1,77 @@
+interface Discriminator {
+	_discriminator: void;
+}
+
+interface FooDiscriminator extends Discriminator {
+	_foo: void;
+}
+
+interface BarDiscriminator extends Discriminator {
+	_bar: void;
+}
+
+interface BaseNode {
+	kind: Discriminator;
+}
+
+interface FooNode extends BaseNode {
+	kind: FooDiscriminator;
+	foo: string;
+}
+
+interface BarNode extends BaseNode {
+	kind: BarDiscriminator;
+	bar: string;
+}
+
+let a: FooDiscriminator;
+let x: FooNode | BarNode;
+
+if (x.kind === a) {
+	x.foo = "yay!";
+}
+else {
+	x; // Not narrowed at present
+}
+
+let z: {
+	value: string;
+	item: FooNode | BarNode;
+}
+if (z.item.kind === a) {
+	z.item.foo = "cool!";
+	z.value = "yes";
+}
+
+let foo: "foo";
+let bar: "bar";
+let foobar: "foobar";
+
+interface Thing {
+	kind: string;
+}
+interface FooThing extends Thing {
+	kind: "foo";
+	foo: string;
+}
+interface BarThing extends Thing {
+	kind: "bar";
+	bar: string;
+}
+interface FooBarThing extends Thing {
+	kind: "foobar";
+	foo: string;
+	bar: string;
+}
+
+let gg: FooThing | BarThing | FooBarThing;
+if (gg.kind === foobar) {
+	gg.bar = "bar";
+	gg.foo = "foo";
+}
+let holder = {
+	value: gg
+};
+if (holder.value.kind === foo) {
+	holder.value.foo = "foo";
+}
\ No newline at end of file