From 12d5296b6cbdfa691e4b42ca2d0a218e2edfc04c Mon Sep 17 00:00:00 2001
From: Anders Hejlsberg <andersh@microsoft.com>
Date: Sat, 26 Jun 2021 09:26:42 -0700
Subject: [PATCH 1/5] Check entire access path is constant when narrowing by
 inlining

---
 src/compiler/checker.ts | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 5625bbc171ea2..aa2196752a13f 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -22975,7 +22975,20 @@ namespace ts {
             }
         }
 
-        function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, isConstant?: boolean, flowContainer?: Node) {
+        function isConstantReference(node: Node): boolean {
+            switch (node.kind) {
+                case SyntaxKind.Identifier:
+                    const symbol = getResolvedSymbol(node as Identifier);
+                    return isConstVariable(symbol) || !!symbol.valueDeclaration && getRootDeclaration(symbol.valueDeclaration).kind === SyntaxKind.Parameter && !isParameterAssigned(symbol);
+                case SyntaxKind.PropertyAccessExpression:
+                case SyntaxKind.ElementAccessExpression:
+                    // The resolvedSymbol property is initialized by checkPropertyAccess or checkElementAccess before we get here.
+                    return isConstantReference((node as AccessExpression).expression) && isReadonlySymbol(getNodeLinks(node).resolvedSymbol || unknownSymbol);
+            }
+            return false;
+        }
+
+        function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node) {
             let key: string | undefined;
             let isKeySet = false;
             let flowDepth = 0;
@@ -24020,11 +24033,11 @@ namespace ts {
                     case SyntaxKind.Identifier:
                         // When narrowing a reference to a const variable, non-assigned parameter, or readonly property, we inline
                         // up to five levels of aliased conditional expressions that are themselves declared as const variables.
-                        if (isConstant && !isMatchingReference(reference, expr) && inlineLevel < 5) {
+                        if (!isMatchingReference(reference, expr) && inlineLevel < 5) {
                             const symbol = getResolvedSymbol(expr as Identifier);
                             if (isConstVariable(symbol)) {
                                 const declaration = symbol.valueDeclaration;
-                                if (declaration && isVariableDeclaration(declaration) && !declaration.type && declaration.initializer) {
+                                if (declaration && isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isConstantReference(reference)) {
                                     inlineLevel++;
                                     const result = narrowType(type, declaration.initializer, assumeTrue);
                                     inlineLevel--;
@@ -24370,12 +24383,12 @@ namespace ts {
             const isOuterVariable = flowContainer !== declarationContainer;
             const isSpreadDestructuringAssignmentTarget = node.parent && node.parent.parent && isSpreadAssignment(node.parent) && isDestructuringAssignmentTarget(node.parent.parent);
             const isModuleExports = symbol.flags & SymbolFlags.ModuleExports;
-            const isConstant = isConstVariable(localOrExportSymbol) && getTypeOfSymbol(localOrExportSymbol) !== autoArrayType || isParameter && !isParameterAssigned(localOrExportSymbol);
             // When the control flow originates in a function expression or arrow function and we are referencing
             // a const variable or parameter from an outer function, we extend the origin of the control flow
             // analysis to include the immediately enclosing function.
-            while (isConstant && flowContainer !== declarationContainer && (flowContainer.kind === SyntaxKind.FunctionExpression ||
-                flowContainer.kind === SyntaxKind.ArrowFunction || isObjectLiteralOrClassExpressionMethod(flowContainer))) {
+            while (flowContainer !== declarationContainer && (flowContainer.kind === SyntaxKind.FunctionExpression ||
+                flowContainer.kind === SyntaxKind.ArrowFunction || isObjectLiteralOrClassExpressionMethod(flowContainer)) &&
+                (isConstVariable(localOrExportSymbol) && type !== autoArrayType || isParameter && !isParameterAssigned(localOrExportSymbol))) {
                 flowContainer = getControlFlowContainer(flowContainer);
             }
             // We only look for uninitialized variables in strict null checking mode, and only when we can analyze
@@ -24390,7 +24403,7 @@ namespace ts {
             const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, declaration as VariableLikeDeclaration) : type) :
                 type === autoType || type === autoArrayType ? undefinedType :
                 getOptionalType(type);
-            const flowType = getFlowTypeOfReference(node, type, initialType, isConstant, flowContainer);
+            const flowType = getFlowTypeOfReference(node, type, initialType, flowContainer);
             // A variable is considered uninitialized when it is possible to analyze the entire control flow graph
             // from declaration to use, and when the variable's declared type doesn't include undefined but the
             // control flow based type does include undefined.
@@ -27608,7 +27621,7 @@ namespace ts {
                 getControlFlowContainer(node) === getControlFlowContainer(prop.valueDeclaration)) {
                 assumeUninitialized = true;
             }
-            const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType, prop && isReadonlySymbol(prop));
+            const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType);
             if (assumeUninitialized && !(getFalsyFlags(propType) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) {
                 error(errorNode, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217
                 // Return the declared type to reduce follow-on errors

From 19eba22294b9f99123e45d5ac53dc6af3cd2c79d Mon Sep 17 00:00:00 2001
From: Anders Hejlsberg <andersh@microsoft.com>
Date: Sat, 26 Jun 2021 14:21:37 -0700
Subject: [PATCH 2/5] Add tests

---
 .../controlFlow/controlFlowAliasing.ts        | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/tests/cases/conformance/controlFlow/controlFlowAliasing.ts b/tests/cases/conformance/controlFlow/controlFlowAliasing.ts
index 9ac9e98c3f2bc..2e16fa29eb78c 100644
--- a/tests/cases/conformance/controlFlow/controlFlowAliasing.ts
+++ b/tests/cases/conformance/controlFlow/controlFlowAliasing.ts
@@ -48,6 +48,36 @@ function f14(x: number | null | undefined): number | null {
     return notUndefined ? x : 0;
 }
 
+function f15(obj: { readonly x: string | number }) {
+    const isString = typeof obj.x === 'string';
+    if (isString) {
+        let s: string = obj.x;
+    }
+}
+
+function f16(obj: { readonly x: string | number }) {
+    const isString = typeof obj.x === 'string';
+    obj = { x: 42 };
+    if (isString) {
+        let s: string = obj.x;  // Not narrowed because of is assigned in function body
+    }
+}
+
+function f17(obj: readonly [string | number]) {
+    const isString = typeof obj[0] === 'string';
+    if (isString) {
+        let s: string = obj[0];
+    }
+}
+
+function f18(obj: readonly [string | number]) {
+    const isString = typeof obj[0] === 'string';
+    obj = [42];
+    if (isString) {
+        let s: string = obj[0];  // Not narrowed because of is assigned in function body
+    }
+}
+
 function f20(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
     const isFoo = obj.kind === 'foo';
     if (isFoo) {

From d535af6cc50bcad492b9b8067253b1d1ed700284 Mon Sep 17 00:00:00 2001
From: Anders Hejlsberg <andersh@microsoft.com>
Date: Sat, 26 Jun 2021 14:21:44 -0700
Subject: [PATCH 3/5] Accept new baselines

---
 .../reference/controlFlowAliasing.errors.txt  |  66 +-
 .../reference/controlFlowAliasing.js          |  64 ++
 .../reference/controlFlowAliasing.symbols     | 627 ++++++++++--------
 .../reference/controlFlowAliasing.types       | 111 ++++
 4 files changed, 586 insertions(+), 282 deletions(-)

diff --git a/tests/baselines/reference/controlFlowAliasing.errors.txt b/tests/baselines/reference/controlFlowAliasing.errors.txt
index d747a3215928a..93bb7936eeebb 100644
--- a/tests/baselines/reference/controlFlowAliasing.errors.txt
+++ b/tests/baselines/reference/controlFlowAliasing.errors.txt
@@ -1,30 +1,34 @@
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(61,13): error TS2339: Property 'foo' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(59,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
+  Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(74,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
+  Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(91,13): error TS2339: Property 'foo' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
   Property 'foo' does not exist on type '{ kind: "bar"; bar: number; }'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(64,13): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(94,13): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
   Property 'bar' does not exist on type '{ kind: "foo"; foo: string; }'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(71,13): error TS2339: Property 'foo' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(101,13): error TS2339: Property 'foo' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
   Property 'foo' does not exist on type '{ kind: "bar"; bar: number; }'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(74,13): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(104,13): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
   Property 'bar' does not exist on type '{ kind: "foo"; foo: string; }'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(82,13): error TS2339: Property 'foo' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(112,13): error TS2339: Property 'foo' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
   Property 'foo' does not exist on type '{ kind: "bar"; bar: number; }'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(85,13): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(115,13): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
   Property 'bar' does not exist on type '{ kind: "foo"; foo: string; }'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(104,13): error TS2339: Property 'foo' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(134,13): error TS2339: Property 'foo' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
   Property 'foo' does not exist on type '{ kind: "bar"; bar: number; }'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(107,13): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(137,13): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
   Property 'bar' does not exist on type '{ kind: "foo"; foo: string; }'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(124,19): error TS2339: Property 'foo' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(154,19): error TS2339: Property 'foo' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
   Property 'foo' does not exist on type '{ kind: "bar"; bar: number; }'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(127,19): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(157,19): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
   Property 'bar' does not exist on type '{ kind: "foo"; foo: string; }'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(207,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(237,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
   Type 'number' is not assignable to type 'string'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(210,13): error TS2322: Type 'string | number' is not assignable to type 'number'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(240,13): error TS2322: Type 'string | number' is not assignable to type 'number'.
   Type 'string' is not assignable to type 'number'.
 
 
-==== tests/cases/conformance/controlFlow/controlFlowAliasing.ts (12 errors) ====
+==== tests/cases/conformance/controlFlow/controlFlowAliasing.ts (14 errors) ====
     // Narrowing by aliased conditional expressions
     
     function f10(x: string | number) {
@@ -72,6 +76,42 @@ tests/cases/conformance/controlFlow/controlFlowAliasing.ts(210,13): error TS2322
         return notUndefined ? x : 0;
     }
     
+    function f15(obj: { readonly x: string | number }) {
+        const isString = typeof obj.x === 'string';
+        if (isString) {
+            let s: string = obj.x;
+        }
+    }
+    
+    function f16(obj: { readonly x: string | number }) {
+        const isString = typeof obj.x === 'string';
+        obj = { x: 42 };
+        if (isString) {
+            let s: string = obj.x;  // Not narrowed because of is assigned in function body
+                ~
+!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
+!!! error TS2322:   Type 'number' is not assignable to type 'string'.
+        }
+    }
+    
+    function f17(obj: readonly [string | number]) {
+        const isString = typeof obj[0] === 'string';
+        if (isString) {
+            let s: string = obj[0];
+        }
+    }
+    
+    function f18(obj: readonly [string | number]) {
+        const isString = typeof obj[0] === 'string';
+        obj = [42];
+        if (isString) {
+            let s: string = obj[0];  // Not narrowed because of is assigned in function body
+                ~
+!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
+!!! error TS2322:   Type 'number' is not assignable to type 'string'.
+        }
+    }
+    
     function f20(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
         const isFoo = obj.kind === 'foo';
         if (isFoo) {
diff --git a/tests/baselines/reference/controlFlowAliasing.js b/tests/baselines/reference/controlFlowAliasing.js
index 91615ba43e139..6f663d2daf71c 100644
--- a/tests/baselines/reference/controlFlowAliasing.js
+++ b/tests/baselines/reference/controlFlowAliasing.js
@@ -46,6 +46,36 @@ function f14(x: number | null | undefined): number | null {
     return notUndefined ? x : 0;
 }
 
+function f15(obj: { readonly x: string | number }) {
+    const isString = typeof obj.x === 'string';
+    if (isString) {
+        let s: string = obj.x;
+    }
+}
+
+function f16(obj: { readonly x: string | number }) {
+    const isString = typeof obj.x === 'string';
+    obj = { x: 42 };
+    if (isString) {
+        let s: string = obj.x;  // Not narrowed because of is assigned in function body
+    }
+}
+
+function f17(obj: readonly [string | number]) {
+    const isString = typeof obj[0] === 'string';
+    if (isString) {
+        let s: string = obj[0];
+    }
+}
+
+function f18(obj: readonly [string | number]) {
+    const isString = typeof obj[0] === 'string';
+    obj = [42];
+    if (isString) {
+        let s: string = obj[0];  // Not narrowed because of is assigned in function body
+    }
+}
+
 function f20(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
     const isFoo = obj.kind === 'foo';
     if (isFoo) {
@@ -256,6 +286,32 @@ function f14(x) {
     var notUndefined = x !== undefined;
     return notUndefined ? x : 0;
 }
+function f15(obj) {
+    var isString = typeof obj.x === 'string';
+    if (isString) {
+        var s = obj.x;
+    }
+}
+function f16(obj) {
+    var isString = typeof obj.x === 'string';
+    obj = { x: 42 };
+    if (isString) {
+        var s = obj.x; // Not narrowed because of is assigned in function body
+    }
+}
+function f17(obj) {
+    var isString = typeof obj[0] === 'string';
+    if (isString) {
+        var s = obj[0];
+    }
+}
+function f18(obj) {
+    var isString = typeof obj[0] === 'string';
+    obj = [42];
+    if (isString) {
+        var s = obj[0]; // Not narrowed because of is assigned in function body
+    }
+}
 function f20(obj) {
     var isFoo = obj.kind === 'foo';
     if (isFoo) {
@@ -413,6 +469,14 @@ declare function f11(x: unknown): void;
 declare function f12(x: string | number | boolean): void;
 declare function f13(x: string | number | boolean): void;
 declare function f14(x: number | null | undefined): number | null;
+declare function f15(obj: {
+    readonly x: string | number;
+}): void;
+declare function f16(obj: {
+    readonly x: string | number;
+}): void;
+declare function f17(obj: readonly [string | number]): void;
+declare function f18(obj: readonly [string | number]): void;
 declare function f20(obj: {
     kind: 'foo';
     foo: string;
diff --git a/tests/baselines/reference/controlFlowAliasing.symbols b/tests/baselines/reference/controlFlowAliasing.symbols
index c8db499c15ac2..efe11532c9b24 100644
--- a/tests/baselines/reference/controlFlowAliasing.symbols
+++ b/tests/baselines/reference/controlFlowAliasing.symbols
@@ -112,491 +112,580 @@ function f14(x: number | null | undefined): number | null {
 >x : Symbol(x, Decl(controlFlowAliasing.ts, 42, 13))
 }
 
-function f20(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
->f20 : Symbol(f20, Decl(controlFlowAliasing.ts, 45, 1))
+function f15(obj: { readonly x: string | number }) {
+>f15 : Symbol(f15, Decl(controlFlowAliasing.ts, 45, 1))
 >obj : Symbol(obj, Decl(controlFlowAliasing.ts, 47, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 47, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 47, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 47, 50))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 47, 63))
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 47, 19))
 
-    const isFoo = obj.kind === 'foo';
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 48, 9))
->obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 47, 19), Decl(controlFlowAliasing.ts, 47, 50))
+    const isString = typeof obj.x === 'string';
+>isString : Symbol(isString, Decl(controlFlowAliasing.ts, 48, 9))
+>obj.x : Symbol(x, Decl(controlFlowAliasing.ts, 47, 19))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 47, 13))
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 47, 19))
+
+    if (isString) {
+>isString : Symbol(isString, Decl(controlFlowAliasing.ts, 48, 9))
+
+        let s: string = obj.x;
+>s : Symbol(s, Decl(controlFlowAliasing.ts, 50, 11))
+>obj.x : Symbol(x, Decl(controlFlowAliasing.ts, 47, 19))
 >obj : Symbol(obj, Decl(controlFlowAliasing.ts, 47, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 47, 19), Decl(controlFlowAliasing.ts, 47, 50))
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 47, 19))
+    }
+}
+
+function f16(obj: { readonly x: string | number }) {
+>f16 : Symbol(f16, Decl(controlFlowAliasing.ts, 52, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 54, 13))
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 54, 19))
+
+    const isString = typeof obj.x === 'string';
+>isString : Symbol(isString, Decl(controlFlowAliasing.ts, 55, 9))
+>obj.x : Symbol(x, Decl(controlFlowAliasing.ts, 54, 19))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 54, 13))
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 54, 19))
+
+    obj = { x: 42 };
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 54, 13))
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 56, 11))
+
+    if (isString) {
+>isString : Symbol(isString, Decl(controlFlowAliasing.ts, 55, 9))
+
+        let s: string = obj.x;  // Not narrowed because of is assigned in function body
+>s : Symbol(s, Decl(controlFlowAliasing.ts, 58, 11))
+>obj.x : Symbol(x, Decl(controlFlowAliasing.ts, 54, 19))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 54, 13))
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 54, 19))
+    }
+}
+
+function f17(obj: readonly [string | number]) {
+>f17 : Symbol(f17, Decl(controlFlowAliasing.ts, 60, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 62, 13))
+
+    const isString = typeof obj[0] === 'string';
+>isString : Symbol(isString, Decl(controlFlowAliasing.ts, 63, 9))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 62, 13))
+>0 : Symbol(0)
+
+    if (isString) {
+>isString : Symbol(isString, Decl(controlFlowAliasing.ts, 63, 9))
+
+        let s: string = obj[0];
+>s : Symbol(s, Decl(controlFlowAliasing.ts, 65, 11))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 62, 13))
+>0 : Symbol(0)
+    }
+}
+
+function f18(obj: readonly [string | number]) {
+>f18 : Symbol(f18, Decl(controlFlowAliasing.ts, 67, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 69, 13))
+
+    const isString = typeof obj[0] === 'string';
+>isString : Symbol(isString, Decl(controlFlowAliasing.ts, 70, 9))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 69, 13))
+>0 : Symbol(0)
+
+    obj = [42];
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 69, 13))
+
+    if (isString) {
+>isString : Symbol(isString, Decl(controlFlowAliasing.ts, 70, 9))
+
+        let s: string = obj[0];  // Not narrowed because of is assigned in function body
+>s : Symbol(s, Decl(controlFlowAliasing.ts, 73, 11))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 69, 13))
+>0 : Symbol(0)
+    }
+}
+
+function f20(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
+>f20 : Symbol(f20, Decl(controlFlowAliasing.ts, 75, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 77, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 77, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 77, 50))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 77, 63))
+
+    const isFoo = obj.kind === 'foo';
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 78, 9))
+>obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 77, 19), Decl(controlFlowAliasing.ts, 77, 50))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 77, 19), Decl(controlFlowAliasing.ts, 77, 50))
 
     if (isFoo) {
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 48, 9))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 78, 9))
 
         obj.foo;
->obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 47, 32))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 47, 13))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 47, 32))
+>obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 77, 32))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 77, 32))
     }
     else {
         obj.bar;
->obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 47, 63))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 47, 13))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 47, 63))
+>obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 77, 63))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 77, 63))
     }
 }
 
 function f21(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
->f21 : Symbol(f21, Decl(controlFlowAliasing.ts, 55, 1))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 57, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 57, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 57, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 57, 50))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 57, 63))
+>f21 : Symbol(f21, Decl(controlFlowAliasing.ts, 85, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 87, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 87, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 87, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 87, 50))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 87, 63))
 
     const isFoo: boolean = obj.kind === 'foo';
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 58, 9))
->obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 57, 19), Decl(controlFlowAliasing.ts, 57, 50))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 57, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 57, 19), Decl(controlFlowAliasing.ts, 57, 50))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 88, 9))
+>obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 87, 19), Decl(controlFlowAliasing.ts, 87, 50))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 87, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 87, 19), Decl(controlFlowAliasing.ts, 87, 50))
 
     if (isFoo) {
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 58, 9))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 88, 9))
 
         obj.foo;  // Not narrowed because isFoo has type annotation
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 57, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 87, 13))
     }
     else {
         obj.bar;  // Not narrowed because isFoo has type annotation
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 57, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 87, 13))
     }
 }
 
 function f22(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
->f22 : Symbol(f22, Decl(controlFlowAliasing.ts, 65, 1))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 67, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 67, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 67, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 67, 50))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 67, 63))
+>f22 : Symbol(f22, Decl(controlFlowAliasing.ts, 95, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 97, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 97, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 97, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 97, 50))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 97, 63))
 
     let isFoo = obj.kind === 'foo';
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 68, 7))
->obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 67, 19), Decl(controlFlowAliasing.ts, 67, 50))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 67, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 67, 19), Decl(controlFlowAliasing.ts, 67, 50))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 98, 7))
+>obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 97, 19), Decl(controlFlowAliasing.ts, 97, 50))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 97, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 97, 19), Decl(controlFlowAliasing.ts, 97, 50))
 
     if (isFoo) {
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 68, 7))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 98, 7))
 
         obj.foo;  // Not narrowed because isFoo is mutable
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 67, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 97, 13))
     }
     else {
         obj.bar;  // Not narrowed because isFoo is mutable
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 67, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 97, 13))
     }
 }
 
 function f23(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
->f23 : Symbol(f23, Decl(controlFlowAliasing.ts, 75, 1))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 77, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 77, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 77, 50))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 77, 63))
+>f23 : Symbol(f23, Decl(controlFlowAliasing.ts, 105, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 107, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 107, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 107, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 107, 50))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 107, 63))
 
     const isFoo = obj.kind === 'foo';
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 78, 9))
->obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 77, 19), Decl(controlFlowAliasing.ts, 77, 50))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 77, 19), Decl(controlFlowAliasing.ts, 77, 50))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 108, 9))
+>obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 107, 19), Decl(controlFlowAliasing.ts, 107, 50))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 107, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 107, 19), Decl(controlFlowAliasing.ts, 107, 50))
 
     obj = obj;
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 107, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 107, 13))
 
     if (isFoo) {
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 78, 9))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 108, 9))
 
         obj.foo;  // Not narrowed because obj is assigned in function body
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 107, 13))
     }
     else {
         obj.bar;  // Not narrowed because obj is assigned in function body
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 107, 13))
     }
 }
 
 function f24(arg: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
->f24 : Symbol(f24, Decl(controlFlowAliasing.ts, 86, 1))
->arg : Symbol(arg, Decl(controlFlowAliasing.ts, 88, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 88, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 88, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 88, 50))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 88, 63))
+>f24 : Symbol(f24, Decl(controlFlowAliasing.ts, 116, 1))
+>arg : Symbol(arg, Decl(controlFlowAliasing.ts, 118, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 118, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 118, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 118, 50))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 118, 63))
 
     const obj = arg;
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 89, 9))
->arg : Symbol(arg, Decl(controlFlowAliasing.ts, 88, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 119, 9))
+>arg : Symbol(arg, Decl(controlFlowAliasing.ts, 118, 13))
 
     const isFoo = obj.kind === 'foo';
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 90, 9))
->obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 88, 19), Decl(controlFlowAliasing.ts, 88, 50))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 89, 9))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 88, 19), Decl(controlFlowAliasing.ts, 88, 50))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 120, 9))
+>obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 118, 19), Decl(controlFlowAliasing.ts, 118, 50))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 119, 9))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 118, 19), Decl(controlFlowAliasing.ts, 118, 50))
 
     if (isFoo) {
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 90, 9))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 120, 9))
 
         obj.foo;
->obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 88, 32))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 89, 9))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 88, 32))
+>obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 118, 32))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 119, 9))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 118, 32))
     }
     else {
         obj.bar;
->obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 88, 63))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 89, 9))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 88, 63))
+>obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 118, 63))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 119, 9))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 118, 63))
     }
 }
 
 function f25(arg: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
->f25 : Symbol(f25, Decl(controlFlowAliasing.ts, 97, 1))
->arg : Symbol(arg, Decl(controlFlowAliasing.ts, 99, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 99, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 99, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 99, 50))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 99, 63))
+>f25 : Symbol(f25, Decl(controlFlowAliasing.ts, 127, 1))
+>arg : Symbol(arg, Decl(controlFlowAliasing.ts, 129, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 129, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 129, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 129, 50))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 129, 63))
 
     let obj = arg;
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 100, 7))
->arg : Symbol(arg, Decl(controlFlowAliasing.ts, 99, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 130, 7))
+>arg : Symbol(arg, Decl(controlFlowAliasing.ts, 129, 13))
 
     const isFoo = obj.kind === 'foo';
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 101, 9))
->obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 99, 19), Decl(controlFlowAliasing.ts, 99, 50))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 100, 7))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 99, 19), Decl(controlFlowAliasing.ts, 99, 50))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 131, 9))
+>obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 129, 19), Decl(controlFlowAliasing.ts, 129, 50))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 130, 7))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 129, 19), Decl(controlFlowAliasing.ts, 129, 50))
 
     if (isFoo) {
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 101, 9))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 131, 9))
 
         obj.foo;  // Not narrowed because obj is mutable
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 100, 7))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 130, 7))
     }
     else {
         obj.bar;  // Not narrowed because obj is mutable
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 100, 7))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 130, 7))
     }
 }
 
 function f26(outer: { readonly obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number } }) {
->f26 : Symbol(f26, Decl(controlFlowAliasing.ts, 108, 1))
->outer : Symbol(outer, Decl(controlFlowAliasing.ts, 110, 13))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 110, 21))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 110, 37))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 110, 50))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 110, 68))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 110, 81))
+>f26 : Symbol(f26, Decl(controlFlowAliasing.ts, 138, 1))
+>outer : Symbol(outer, Decl(controlFlowAliasing.ts, 140, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 140, 21))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 140, 37))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 140, 50))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 140, 68))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 140, 81))
 
     const isFoo = outer.obj.kind === 'foo';
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 111, 9))
->outer.obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 110, 37), Decl(controlFlowAliasing.ts, 110, 68))
->outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 110, 21))
->outer : Symbol(outer, Decl(controlFlowAliasing.ts, 110, 13))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 110, 21))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 110, 37), Decl(controlFlowAliasing.ts, 110, 68))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 141, 9))
+>outer.obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 140, 37), Decl(controlFlowAliasing.ts, 140, 68))
+>outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 140, 21))
+>outer : Symbol(outer, Decl(controlFlowAliasing.ts, 140, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 140, 21))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 140, 37), Decl(controlFlowAliasing.ts, 140, 68))
 
     if (isFoo) {
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 111, 9))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 141, 9))
 
         outer.obj.foo;
->outer.obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 110, 50))
->outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 110, 21))
->outer : Symbol(outer, Decl(controlFlowAliasing.ts, 110, 13))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 110, 21))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 110, 50))
+>outer.obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 140, 50))
+>outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 140, 21))
+>outer : Symbol(outer, Decl(controlFlowAliasing.ts, 140, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 140, 21))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 140, 50))
     }
     else {
         outer.obj.bar;
->outer.obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 110, 81))
->outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 110, 21))
->outer : Symbol(outer, Decl(controlFlowAliasing.ts, 110, 13))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 110, 21))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 110, 81))
+>outer.obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 140, 81))
+>outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 140, 21))
+>outer : Symbol(outer, Decl(controlFlowAliasing.ts, 140, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 140, 21))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 140, 81))
     }
 }
 
 function f27(outer: { obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number } }) {
->f27 : Symbol(f27, Decl(controlFlowAliasing.ts, 118, 1))
->outer : Symbol(outer, Decl(controlFlowAliasing.ts, 120, 13))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 120, 21))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 120, 28))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 120, 41))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 120, 59))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 120, 72))
+>f27 : Symbol(f27, Decl(controlFlowAliasing.ts, 148, 1))
+>outer : Symbol(outer, Decl(controlFlowAliasing.ts, 150, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 150, 21))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 150, 28))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 150, 41))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 150, 59))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 150, 72))
 
     const isFoo = outer.obj.kind === 'foo';
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 121, 9))
->outer.obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 120, 28), Decl(controlFlowAliasing.ts, 120, 59))
->outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 120, 21))
->outer : Symbol(outer, Decl(controlFlowAliasing.ts, 120, 13))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 120, 21))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 120, 28), Decl(controlFlowAliasing.ts, 120, 59))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 151, 9))
+>outer.obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 150, 28), Decl(controlFlowAliasing.ts, 150, 59))
+>outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 150, 21))
+>outer : Symbol(outer, Decl(controlFlowAliasing.ts, 150, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 150, 21))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 150, 28), Decl(controlFlowAliasing.ts, 150, 59))
 
     if (isFoo) {
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 121, 9))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 151, 9))
 
         outer.obj.foo;  // Not narrowed because obj is mutable
->outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 120, 21))
->outer : Symbol(outer, Decl(controlFlowAliasing.ts, 120, 13))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 120, 21))
+>outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 150, 21))
+>outer : Symbol(outer, Decl(controlFlowAliasing.ts, 150, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 150, 21))
     }
     else {
         outer.obj.bar;  // Not narrowed because obj is mutable
->outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 120, 21))
->outer : Symbol(outer, Decl(controlFlowAliasing.ts, 120, 13))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 120, 21))
+>outer.obj : Symbol(obj, Decl(controlFlowAliasing.ts, 150, 21))
+>outer : Symbol(outer, Decl(controlFlowAliasing.ts, 150, 13))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 150, 21))
     }
 }
 
 function f28(obj?: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
->f28 : Symbol(f28, Decl(controlFlowAliasing.ts, 128, 1))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 130, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 130, 20))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 130, 33))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 130, 51))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 130, 64))
+>f28 : Symbol(f28, Decl(controlFlowAliasing.ts, 158, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 160, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 160, 20))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 160, 33))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 160, 51))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 160, 64))
 
     const isFoo = obj && obj.kind === 'foo';
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 131, 9))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 130, 13))
->obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 130, 20), Decl(controlFlowAliasing.ts, 130, 51))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 130, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 130, 20), Decl(controlFlowAliasing.ts, 130, 51))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 161, 9))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 160, 13))
+>obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 160, 20), Decl(controlFlowAliasing.ts, 160, 51))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 160, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 160, 20), Decl(controlFlowAliasing.ts, 160, 51))
 
     const isBar = obj && obj.kind === 'bar';
->isBar : Symbol(isBar, Decl(controlFlowAliasing.ts, 132, 9))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 130, 13))
->obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 130, 20), Decl(controlFlowAliasing.ts, 130, 51))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 130, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 130, 20), Decl(controlFlowAliasing.ts, 130, 51))
+>isBar : Symbol(isBar, Decl(controlFlowAliasing.ts, 162, 9))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 160, 13))
+>obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 160, 20), Decl(controlFlowAliasing.ts, 160, 51))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 160, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 160, 20), Decl(controlFlowAliasing.ts, 160, 51))
 
     if (isFoo) {
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 131, 9))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 161, 9))
 
         obj.foo;
->obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 130, 33))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 130, 13))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 130, 33))
+>obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 160, 33))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 160, 13))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 160, 33))
     }
     if (isBar) {
->isBar : Symbol(isBar, Decl(controlFlowAliasing.ts, 132, 9))
+>isBar : Symbol(isBar, Decl(controlFlowAliasing.ts, 162, 9))
 
         obj.bar;
->obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 130, 64))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 130, 13))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 130, 64))
+>obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 160, 64))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 160, 13))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 160, 64))
     }
 }
 
 // Narrowing by aliased discriminant property access
 
 function f30(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
->f30 : Symbol(f30, Decl(controlFlowAliasing.ts, 139, 1))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 143, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 143, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 143, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 143, 50))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 143, 63))
+>f30 : Symbol(f30, Decl(controlFlowAliasing.ts, 169, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 173, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 173, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 173, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 173, 50))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 173, 63))
 
     const kind = obj.kind;
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 144, 9))
->obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 143, 19), Decl(controlFlowAliasing.ts, 143, 50))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 143, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 143, 19), Decl(controlFlowAliasing.ts, 143, 50))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 174, 9))
+>obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 173, 19), Decl(controlFlowAliasing.ts, 173, 50))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 173, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 173, 19), Decl(controlFlowAliasing.ts, 173, 50))
 
     if (kind === 'foo') {
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 144, 9))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 174, 9))
 
         obj.foo;
->obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 143, 32))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 143, 13))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 143, 32))
+>obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 173, 32))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 173, 13))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 173, 32))
     }
     else {
         obj.bar;
->obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 143, 63))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 143, 13))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 143, 63))
+>obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 173, 63))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 173, 13))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 173, 63))
     }
 }
 
 function f31(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
->f31 : Symbol(f31, Decl(controlFlowAliasing.ts, 151, 1))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 153, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 153, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 153, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 153, 50))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 153, 63))
+>f31 : Symbol(f31, Decl(controlFlowAliasing.ts, 181, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 183, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 183, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 183, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 183, 50))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 183, 63))
 
     const { kind } = obj;
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 154, 11))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 153, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 184, 11))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 183, 13))
 
     if (kind === 'foo') {
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 154, 11))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 184, 11))
 
         obj.foo;
->obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 153, 32))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 153, 13))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 153, 32))
+>obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 183, 32))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 183, 13))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 183, 32))
     }
     else {
         obj.bar;
->obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 153, 63))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 153, 13))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 153, 63))
+>obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 183, 63))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 183, 13))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 183, 63))
     }
 }
 
 function f32(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
->f32 : Symbol(f32, Decl(controlFlowAliasing.ts, 161, 1))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 163, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 163, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 163, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 163, 50))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 163, 63))
+>f32 : Symbol(f32, Decl(controlFlowAliasing.ts, 191, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 193, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 193, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 193, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 193, 50))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 193, 63))
 
     const { kind: k } = obj;
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 163, 19), Decl(controlFlowAliasing.ts, 163, 50))
->k : Symbol(k, Decl(controlFlowAliasing.ts, 164, 11))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 163, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 193, 19), Decl(controlFlowAliasing.ts, 193, 50))
+>k : Symbol(k, Decl(controlFlowAliasing.ts, 194, 11))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 193, 13))
 
     if (k === 'foo') {
->k : Symbol(k, Decl(controlFlowAliasing.ts, 164, 11))
+>k : Symbol(k, Decl(controlFlowAliasing.ts, 194, 11))
 
         obj.foo;
->obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 163, 32))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 163, 13))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 163, 32))
+>obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 193, 32))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 193, 13))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 193, 32))
     }
     else {
         obj.bar;
->obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 163, 63))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 163, 13))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 163, 63))
+>obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 193, 63))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 193, 13))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 193, 63))
     }
 }
 
 function f33(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
->f33 : Symbol(f33, Decl(controlFlowAliasing.ts, 171, 1))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 173, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 173, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 173, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 173, 50))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 173, 63))
+>f33 : Symbol(f33, Decl(controlFlowAliasing.ts, 201, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 203, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 203, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 203, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 203, 50))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 203, 63))
 
     const { kind } = obj;
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 174, 11))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 173, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 204, 11))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 203, 13))
 
     switch (kind) {
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 174, 11))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 204, 11))
 
         case 'foo': obj.foo; break;
->obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 173, 32))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 173, 13))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 173, 32))
+>obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 203, 32))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 203, 13))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 203, 32))
 
         case 'bar': obj.bar; break;
->obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 173, 63))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 173, 13))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 173, 63))
+>obj.bar : Symbol(bar, Decl(controlFlowAliasing.ts, 203, 63))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 203, 13))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 203, 63))
     }
 }
 
 // Mixing of aliased discriminants and conditionals
 
 function f40(obj: { kind: 'foo', foo?: string } | { kind: 'bar', bar?: number }) {
->f40 : Symbol(f40, Decl(controlFlowAliasing.ts, 179, 1))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 183, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 183, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 183, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 183, 51))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 183, 64))
+>f40 : Symbol(f40, Decl(controlFlowAliasing.ts, 209, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 213, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 213, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 213, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 213, 51))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 213, 64))
 
     const { kind } = obj;
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 184, 11))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 183, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 214, 11))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 213, 13))
 
     const isFoo = kind == 'foo';
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 185, 9))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 184, 11))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 215, 9))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 214, 11))
 
     if (isFoo && obj.foo) {
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 185, 9))
->obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 183, 32))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 183, 13))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 183, 32))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 215, 9))
+>obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 213, 32))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 213, 13))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 213, 32))
 
         let t: string = obj.foo;
->t : Symbol(t, Decl(controlFlowAliasing.ts, 187, 11))
->obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 183, 32))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 183, 13))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 183, 32))
+>t : Symbol(t, Decl(controlFlowAliasing.ts, 217, 11))
+>obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 213, 32))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 213, 13))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 213, 32))
     }
 }
 
 // Unsupported narrowing of destructured payload by destructured discriminant
 
 type Data = { kind: 'str', payload: string } | { kind: 'num', payload: number };
->Data : Symbol(Data, Decl(controlFlowAliasing.ts, 189, 1))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 193, 13))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 193, 26))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 193, 48))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 193, 61))
+>Data : Symbol(Data, Decl(controlFlowAliasing.ts, 219, 1))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 223, 13))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 26))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 223, 48))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 61))
 
 function gg2(obj: Data) {
->gg2 : Symbol(gg2, Decl(controlFlowAliasing.ts, 193, 80))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 195, 13))
->Data : Symbol(Data, Decl(controlFlowAliasing.ts, 189, 1))
+>gg2 : Symbol(gg2, Decl(controlFlowAliasing.ts, 223, 80))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 225, 13))
+>Data : Symbol(Data, Decl(controlFlowAliasing.ts, 219, 1))
 
     if (obj.kind === 'str') {
->obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 193, 13), Decl(controlFlowAliasing.ts, 193, 48))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 195, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 193, 13), Decl(controlFlowAliasing.ts, 193, 48))
+>obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 223, 13), Decl(controlFlowAliasing.ts, 223, 48))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 225, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 223, 13), Decl(controlFlowAliasing.ts, 223, 48))
 
         let t: string = obj.payload;
->t : Symbol(t, Decl(controlFlowAliasing.ts, 197, 11))
->obj.payload : Symbol(payload, Decl(controlFlowAliasing.ts, 193, 26))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 195, 13))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 193, 26))
+>t : Symbol(t, Decl(controlFlowAliasing.ts, 227, 11))
+>obj.payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 26))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 225, 13))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 26))
     }
     else {
         let t: number = obj.payload;
->t : Symbol(t, Decl(controlFlowAliasing.ts, 200, 11))
->obj.payload : Symbol(payload, Decl(controlFlowAliasing.ts, 193, 61))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 195, 13))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 193, 61))
+>t : Symbol(t, Decl(controlFlowAliasing.ts, 230, 11))
+>obj.payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 61))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 225, 13))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 61))
     }
 }
 
 function foo({ kind, payload }: Data) {
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 202, 1))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 204, 14))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 204, 20))
->Data : Symbol(Data, Decl(controlFlowAliasing.ts, 189, 1))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 232, 1))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 234, 14))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 234, 20))
+>Data : Symbol(Data, Decl(controlFlowAliasing.ts, 219, 1))
 
     if (kind === 'str') {
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 204, 14))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 234, 14))
 
         let t: string = payload;
->t : Symbol(t, Decl(controlFlowAliasing.ts, 206, 11))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 204, 20))
+>t : Symbol(t, Decl(controlFlowAliasing.ts, 236, 11))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 234, 20))
     }
     else {
         let t: number = payload;
->t : Symbol(t, Decl(controlFlowAliasing.ts, 209, 11))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 204, 20))
+>t : Symbol(t, Decl(controlFlowAliasing.ts, 239, 11))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 234, 20))
     }
 }
 
diff --git a/tests/baselines/reference/controlFlowAliasing.types b/tests/baselines/reference/controlFlowAliasing.types
index a3af9609566a1..5db01a1cc0498 100644
--- a/tests/baselines/reference/controlFlowAliasing.types
+++ b/tests/baselines/reference/controlFlowAliasing.types
@@ -137,6 +137,117 @@ function f14(x: number | null | undefined): number | null {
 >0 : 0
 }
 
+function f15(obj: { readonly x: string | number }) {
+>f15 : (obj: {    readonly x: string | number;}) => void
+>obj : { readonly x: string | number; }
+>x : string | number
+
+    const isString = typeof obj.x === 'string';
+>isString : boolean
+>typeof obj.x === 'string' : boolean
+>typeof obj.x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
+>obj.x : string | number
+>obj : { readonly x: string | number; }
+>x : string | number
+>'string' : "string"
+
+    if (isString) {
+>isString : boolean
+
+        let s: string = obj.x;
+>s : string
+>obj.x : string
+>obj : { readonly x: string | number; }
+>x : string
+    }
+}
+
+function f16(obj: { readonly x: string | number }) {
+>f16 : (obj: {    readonly x: string | number;}) => void
+>obj : { readonly x: string | number; }
+>x : string | number
+
+    const isString = typeof obj.x === 'string';
+>isString : boolean
+>typeof obj.x === 'string' : boolean
+>typeof obj.x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
+>obj.x : string | number
+>obj : { readonly x: string | number; }
+>x : string | number
+>'string' : "string"
+
+    obj = { x: 42 };
+>obj = { x: 42 } : { x: number; }
+>obj : { readonly x: string | number; }
+>{ x: 42 } : { x: number; }
+>x : number
+>42 : 42
+
+    if (isString) {
+>isString : boolean
+
+        let s: string = obj.x;  // Not narrowed because of is assigned in function body
+>s : string
+>obj.x : string | number
+>obj : { readonly x: string | number; }
+>x : string | number
+    }
+}
+
+function f17(obj: readonly [string | number]) {
+>f17 : (obj: readonly [string | number]) => void
+>obj : readonly [string | number]
+
+    const isString = typeof obj[0] === 'string';
+>isString : boolean
+>typeof obj[0] === 'string' : boolean
+>typeof obj[0] : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
+>obj[0] : string | number
+>obj : readonly [string | number]
+>0 : 0
+>'string' : "string"
+
+    if (isString) {
+>isString : boolean
+
+        let s: string = obj[0];
+>s : string
+>obj[0] : string
+>obj : readonly [string | number]
+>0 : 0
+    }
+}
+
+function f18(obj: readonly [string | number]) {
+>f18 : (obj: readonly [string | number]) => void
+>obj : readonly [string | number]
+
+    const isString = typeof obj[0] === 'string';
+>isString : boolean
+>typeof obj[0] === 'string' : boolean
+>typeof obj[0] : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
+>obj[0] : string | number
+>obj : readonly [string | number]
+>0 : 0
+>'string' : "string"
+
+    obj = [42];
+>obj = [42] : [number]
+>obj : readonly [string | number]
+>[42] : [number]
+>42 : 42
+
+    if (isString) {
+>isString : boolean
+
+        let s: string = obj[0];  // Not narrowed because of is assigned in function body
+>s : string
+>obj[0] : string | number
+>obj : readonly [string | number]
+>0 : 0
+    }
+}
+
 function f20(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
 >f20 : (obj: {    kind: 'foo';    foo: string;} | {    kind: 'bar';    bar: number;}) => void
 >obj : { kind: 'foo'; foo: string; } | { kind: 'bar'; bar: number; }

From 6f86803827a388d2d7b26f979fdf8ce6e070df33 Mon Sep 17 00:00:00 2001
From: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
Date: Mon, 28 Jun 2021 22:39:34 +0000
Subject: [PATCH 4/5] Added test cases for parameter properties.

---
 .../controlFlow/controlFlowAliasing.ts        | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/tests/cases/conformance/controlFlow/controlFlowAliasing.ts b/tests/cases/conformance/controlFlow/controlFlowAliasing.ts
index 2e16fa29eb78c..b8d2a81fb1a09 100644
--- a/tests/cases/conformance/controlFlow/controlFlowAliasing.ts
+++ b/tests/cases/conformance/controlFlow/controlFlowAliasing.ts
@@ -212,6 +212,36 @@ function f33(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
     }
 }
 
+
+class C10 {
+    constructor(readonly x: string | number) {
+        const thisX_isString = typeof this.x === 'string';
+        const xIsString = typeof x === 'string';
+        if (thisX_isString && xIsString) {
+            let s: string;
+            s = this.x;
+            s = x;
+        }
+    }
+}
+
+class C11 {
+    constructor(readonly x: string | number) {
+        const thisX_isString = typeof this.x === 'string';
+        const xIsString = typeof x === 'string';
+        if (thisX_isString && xIsString) {
+            // Some narrowings may be invalidated due to later assignments.
+            let s: string;
+            s = this.x;
+            s = x;
+        }
+        else {
+            this.x = 10;
+            x = 10;
+        }
+    }
+}
+
 // Mixing of aliased discriminants and conditionals
 
 function f40(obj: { kind: 'foo', foo?: string } | { kind: 'bar', bar?: number }) {

From 3b12c042546aea831c2a2b8df096a7bca31df552 Mon Sep 17 00:00:00 2001
From: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
Date: Mon, 28 Jun 2021 22:41:52 +0000
Subject: [PATCH 5/5] Accepted baselines.

---
 .../reference/controlFlowAliasing.errors.txt  |  51 ++++-
 .../reference/controlFlowAliasing.js          |  69 +++++++
 .../reference/controlFlowAliasing.symbols     | 175 +++++++++++++-----
 .../reference/controlFlowAliasing.types       | 105 +++++++++++
 4 files changed, 351 insertions(+), 49 deletions(-)

diff --git a/tests/baselines/reference/controlFlowAliasing.errors.txt b/tests/baselines/reference/controlFlowAliasing.errors.txt
index 93bb7936eeebb..a29ae9e2faf52 100644
--- a/tests/baselines/reference/controlFlowAliasing.errors.txt
+++ b/tests/baselines/reference/controlFlowAliasing.errors.txt
@@ -22,13 +22,19 @@ tests/cases/conformance/controlFlow/controlFlowAliasing.ts(154,19): error TS2339
   Property 'foo' does not exist on type '{ kind: "bar"; bar: number; }'.
 tests/cases/conformance/controlFlow/controlFlowAliasing.ts(157,19): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
   Property 'bar' does not exist on type '{ kind: "foo"; foo: string; }'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(237,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(219,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
   Type 'number' is not assignable to type 'string'.
-tests/cases/conformance/controlFlow/controlFlowAliasing.ts(240,13): error TS2322: Type 'string | number' is not assignable to type 'number'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(232,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
+  Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(233,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
+  Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(267,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
+  Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/controlFlow/controlFlowAliasing.ts(270,13): error TS2322: Type 'string | number' is not assignable to type 'number'.
   Type 'string' is not assignable to type 'number'.
 
 
-==== tests/cases/conformance/controlFlow/controlFlowAliasing.ts (14 errors) ====
+==== tests/cases/conformance/controlFlow/controlFlowAliasing.ts (17 errors) ====
     // Narrowing by aliased conditional expressions
     
     function f10(x: string | number) {
@@ -276,6 +282,45 @@ tests/cases/conformance/controlFlow/controlFlowAliasing.ts(240,13): error TS2322
         }
     }
     
+    
+    class C10 {
+        constructor(readonly x: string | number) {
+            const thisX_isString = typeof this.x === 'string';
+            const xIsString = typeof x === 'string';
+            if (thisX_isString && xIsString) {
+                let s: string;
+                s = this.x;
+                ~
+!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
+!!! error TS2322:   Type 'number' is not assignable to type 'string'.
+                s = x;
+            }
+        }
+    }
+    
+    class C11 {
+        constructor(readonly x: string | number) {
+            const thisX_isString = typeof this.x === 'string';
+            const xIsString = typeof x === 'string';
+            if (thisX_isString && xIsString) {
+                // Some narrowings may be invalidated due to later assignments.
+                let s: string;
+                s = this.x;
+                ~
+!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
+!!! error TS2322:   Type 'number' is not assignable to type 'string'.
+                s = x;
+                ~
+!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
+!!! error TS2322:   Type 'number' is not assignable to type 'string'.
+            }
+            else {
+                this.x = 10;
+                x = 10;
+            }
+        }
+    }
+    
     // Mixing of aliased discriminants and conditionals
     
     function f40(obj: { kind: 'foo', foo?: string } | { kind: 'bar', bar?: number }) {
diff --git a/tests/baselines/reference/controlFlowAliasing.js b/tests/baselines/reference/controlFlowAliasing.js
index 6f663d2daf71c..4ed26e586c3f6 100644
--- a/tests/baselines/reference/controlFlowAliasing.js
+++ b/tests/baselines/reference/controlFlowAliasing.js
@@ -210,6 +210,36 @@ function f33(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
     }
 }
 
+
+class C10 {
+    constructor(readonly x: string | number) {
+        const thisX_isString = typeof this.x === 'string';
+        const xIsString = typeof x === 'string';
+        if (thisX_isString && xIsString) {
+            let s: string;
+            s = this.x;
+            s = x;
+        }
+    }
+}
+
+class C11 {
+    constructor(readonly x: string | number) {
+        const thisX_isString = typeof this.x === 'string';
+        const xIsString = typeof x === 'string';
+        if (thisX_isString && xIsString) {
+            // Some narrowings may be invalidated due to later assignments.
+            let s: string;
+            s = this.x;
+            s = x;
+        }
+        else {
+            this.x = 10;
+            x = 10;
+        }
+    }
+}
+
 // Mixing of aliased discriminants and conditionals
 
 function f40(obj: { kind: 'foo', foo?: string } | { kind: 'bar', bar?: number }) {
@@ -436,6 +466,37 @@ function f33(obj) {
             break;
     }
 }
+var C10 = /** @class */ (function () {
+    function C10(x) {
+        this.x = x;
+        var thisX_isString = typeof this.x === 'string';
+        var xIsString = typeof x === 'string';
+        if (thisX_isString && xIsString) {
+            var s = void 0;
+            s = this.x;
+            s = x;
+        }
+    }
+    return C10;
+}());
+var C11 = /** @class */ (function () {
+    function C11(x) {
+        this.x = x;
+        var thisX_isString = typeof this.x === 'string';
+        var xIsString = typeof x === 'string';
+        if (thisX_isString && xIsString) {
+            // Some narrowings may be invalidated due to later assignments.
+            var s = void 0;
+            s = this.x;
+            s = x;
+        }
+        else {
+            this.x = 10;
+            x = 10;
+        }
+    }
+    return C11;
+}());
 // Mixing of aliased discriminants and conditionals
 function f40(obj) {
     var kind = obj.kind;
@@ -572,6 +633,14 @@ declare function f33(obj: {
     kind: 'bar';
     bar: number;
 }): void;
+declare class C10 {
+    readonly x: string | number;
+    constructor(x: string | number);
+}
+declare class C11 {
+    readonly x: string | number;
+    constructor(x: string | number);
+}
 declare function f40(obj: {
     kind: 'foo';
     foo?: string;
diff --git a/tests/baselines/reference/controlFlowAliasing.symbols b/tests/baselines/reference/controlFlowAliasing.symbols
index efe11532c9b24..6fb00b3428182 100644
--- a/tests/baselines/reference/controlFlowAliasing.symbols
+++ b/tests/baselines/reference/controlFlowAliasing.symbols
@@ -603,89 +603,172 @@ function f33(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
     }
 }
 
+
+class C10 {
+>C10 : Symbol(C10, Decl(controlFlowAliasing.ts, 209, 1))
+
+    constructor(readonly x: string | number) {
+>x : Symbol(C10.x, Decl(controlFlowAliasing.ts, 213, 16))
+
+        const thisX_isString = typeof this.x === 'string';
+>thisX_isString : Symbol(thisX_isString, Decl(controlFlowAliasing.ts, 214, 13))
+>this.x : Symbol(C10.x, Decl(controlFlowAliasing.ts, 213, 16))
+>this : Symbol(C10, Decl(controlFlowAliasing.ts, 209, 1))
+>x : Symbol(C10.x, Decl(controlFlowAliasing.ts, 213, 16))
+
+        const xIsString = typeof x === 'string';
+>xIsString : Symbol(xIsString, Decl(controlFlowAliasing.ts, 215, 13))
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 213, 16))
+
+        if (thisX_isString && xIsString) {
+>thisX_isString : Symbol(thisX_isString, Decl(controlFlowAliasing.ts, 214, 13))
+>xIsString : Symbol(xIsString, Decl(controlFlowAliasing.ts, 215, 13))
+
+            let s: string;
+>s : Symbol(s, Decl(controlFlowAliasing.ts, 217, 15))
+
+            s = this.x;
+>s : Symbol(s, Decl(controlFlowAliasing.ts, 217, 15))
+>this.x : Symbol(C10.x, Decl(controlFlowAliasing.ts, 213, 16))
+>this : Symbol(C10, Decl(controlFlowAliasing.ts, 209, 1))
+>x : Symbol(C10.x, Decl(controlFlowAliasing.ts, 213, 16))
+
+            s = x;
+>s : Symbol(s, Decl(controlFlowAliasing.ts, 217, 15))
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 213, 16))
+        }
+    }
+}
+
+class C11 {
+>C11 : Symbol(C11, Decl(controlFlowAliasing.ts, 222, 1))
+
+    constructor(readonly x: string | number) {
+>x : Symbol(C11.x, Decl(controlFlowAliasing.ts, 225, 16))
+
+        const thisX_isString = typeof this.x === 'string';
+>thisX_isString : Symbol(thisX_isString, Decl(controlFlowAliasing.ts, 226, 13))
+>this.x : Symbol(C11.x, Decl(controlFlowAliasing.ts, 225, 16))
+>this : Symbol(C11, Decl(controlFlowAliasing.ts, 222, 1))
+>x : Symbol(C11.x, Decl(controlFlowAliasing.ts, 225, 16))
+
+        const xIsString = typeof x === 'string';
+>xIsString : Symbol(xIsString, Decl(controlFlowAliasing.ts, 227, 13))
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 225, 16))
+
+        if (thisX_isString && xIsString) {
+>thisX_isString : Symbol(thisX_isString, Decl(controlFlowAliasing.ts, 226, 13))
+>xIsString : Symbol(xIsString, Decl(controlFlowAliasing.ts, 227, 13))
+
+            // Some narrowings may be invalidated due to later assignments.
+            let s: string;
+>s : Symbol(s, Decl(controlFlowAliasing.ts, 230, 15))
+
+            s = this.x;
+>s : Symbol(s, Decl(controlFlowAliasing.ts, 230, 15))
+>this.x : Symbol(C11.x, Decl(controlFlowAliasing.ts, 225, 16))
+>this : Symbol(C11, Decl(controlFlowAliasing.ts, 222, 1))
+>x : Symbol(C11.x, Decl(controlFlowAliasing.ts, 225, 16))
+
+            s = x;
+>s : Symbol(s, Decl(controlFlowAliasing.ts, 230, 15))
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 225, 16))
+        }
+        else {
+            this.x = 10;
+>this.x : Symbol(C11.x, Decl(controlFlowAliasing.ts, 225, 16))
+>this : Symbol(C11, Decl(controlFlowAliasing.ts, 222, 1))
+>x : Symbol(C11.x, Decl(controlFlowAliasing.ts, 225, 16))
+
+            x = 10;
+>x : Symbol(x, Decl(controlFlowAliasing.ts, 225, 16))
+        }
+    }
+}
+
 // Mixing of aliased discriminants and conditionals
 
 function f40(obj: { kind: 'foo', foo?: string } | { kind: 'bar', bar?: number }) {
->f40 : Symbol(f40, Decl(controlFlowAliasing.ts, 209, 1))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 213, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 213, 19))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 213, 32))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 213, 51))
->bar : Symbol(bar, Decl(controlFlowAliasing.ts, 213, 64))
+>f40 : Symbol(f40, Decl(controlFlowAliasing.ts, 239, 1))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 243, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 243, 19))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 243, 32))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 243, 51))
+>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 243, 64))
 
     const { kind } = obj;
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 214, 11))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 213, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 244, 11))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 243, 13))
 
     const isFoo = kind == 'foo';
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 215, 9))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 214, 11))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 245, 9))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 244, 11))
 
     if (isFoo && obj.foo) {
->isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 215, 9))
->obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 213, 32))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 213, 13))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 213, 32))
+>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 245, 9))
+>obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 243, 32))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 243, 13))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 243, 32))
 
         let t: string = obj.foo;
->t : Symbol(t, Decl(controlFlowAliasing.ts, 217, 11))
->obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 213, 32))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 213, 13))
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 213, 32))
+>t : Symbol(t, Decl(controlFlowAliasing.ts, 247, 11))
+>obj.foo : Symbol(foo, Decl(controlFlowAliasing.ts, 243, 32))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 243, 13))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 243, 32))
     }
 }
 
 // Unsupported narrowing of destructured payload by destructured discriminant
 
 type Data = { kind: 'str', payload: string } | { kind: 'num', payload: number };
->Data : Symbol(Data, Decl(controlFlowAliasing.ts, 219, 1))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 223, 13))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 26))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 223, 48))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 61))
+>Data : Symbol(Data, Decl(controlFlowAliasing.ts, 249, 1))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 253, 13))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 253, 26))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 253, 48))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 253, 61))
 
 function gg2(obj: Data) {
->gg2 : Symbol(gg2, Decl(controlFlowAliasing.ts, 223, 80))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 225, 13))
->Data : Symbol(Data, Decl(controlFlowAliasing.ts, 219, 1))
+>gg2 : Symbol(gg2, Decl(controlFlowAliasing.ts, 253, 80))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 255, 13))
+>Data : Symbol(Data, Decl(controlFlowAliasing.ts, 249, 1))
 
     if (obj.kind === 'str') {
->obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 223, 13), Decl(controlFlowAliasing.ts, 223, 48))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 225, 13))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 223, 13), Decl(controlFlowAliasing.ts, 223, 48))
+>obj.kind : Symbol(kind, Decl(controlFlowAliasing.ts, 253, 13), Decl(controlFlowAliasing.ts, 253, 48))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 255, 13))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 253, 13), Decl(controlFlowAliasing.ts, 253, 48))
 
         let t: string = obj.payload;
->t : Symbol(t, Decl(controlFlowAliasing.ts, 227, 11))
->obj.payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 26))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 225, 13))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 26))
+>t : Symbol(t, Decl(controlFlowAliasing.ts, 257, 11))
+>obj.payload : Symbol(payload, Decl(controlFlowAliasing.ts, 253, 26))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 255, 13))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 253, 26))
     }
     else {
         let t: number = obj.payload;
->t : Symbol(t, Decl(controlFlowAliasing.ts, 230, 11))
->obj.payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 61))
->obj : Symbol(obj, Decl(controlFlowAliasing.ts, 225, 13))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 223, 61))
+>t : Symbol(t, Decl(controlFlowAliasing.ts, 260, 11))
+>obj.payload : Symbol(payload, Decl(controlFlowAliasing.ts, 253, 61))
+>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 255, 13))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 253, 61))
     }
 }
 
 function foo({ kind, payload }: Data) {
->foo : Symbol(foo, Decl(controlFlowAliasing.ts, 232, 1))
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 234, 14))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 234, 20))
->Data : Symbol(Data, Decl(controlFlowAliasing.ts, 219, 1))
+>foo : Symbol(foo, Decl(controlFlowAliasing.ts, 262, 1))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 264, 14))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 264, 20))
+>Data : Symbol(Data, Decl(controlFlowAliasing.ts, 249, 1))
 
     if (kind === 'str') {
->kind : Symbol(kind, Decl(controlFlowAliasing.ts, 234, 14))
+>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 264, 14))
 
         let t: string = payload;
->t : Symbol(t, Decl(controlFlowAliasing.ts, 236, 11))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 234, 20))
+>t : Symbol(t, Decl(controlFlowAliasing.ts, 266, 11))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 264, 20))
     }
     else {
         let t: number = payload;
->t : Symbol(t, Decl(controlFlowAliasing.ts, 239, 11))
->payload : Symbol(payload, Decl(controlFlowAliasing.ts, 234, 20))
+>t : Symbol(t, Decl(controlFlowAliasing.ts, 269, 11))
+>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 264, 20))
     }
 }
 
diff --git a/tests/baselines/reference/controlFlowAliasing.types b/tests/baselines/reference/controlFlowAliasing.types
index 5db01a1cc0498..aced9845a07d6 100644
--- a/tests/baselines/reference/controlFlowAliasing.types
+++ b/tests/baselines/reference/controlFlowAliasing.types
@@ -701,6 +701,111 @@ function f33(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
     }
 }
 
+
+class C10 {
+>C10 : C10
+
+    constructor(readonly x: string | number) {
+>x : string | number
+
+        const thisX_isString = typeof this.x === 'string';
+>thisX_isString : boolean
+>typeof this.x === 'string' : boolean
+>typeof this.x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
+>this.x : string | number
+>this : this
+>x : string | number
+>'string' : "string"
+
+        const xIsString = typeof x === 'string';
+>xIsString : boolean
+>typeof x === 'string' : boolean
+>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
+>x : string | number
+>'string' : "string"
+
+        if (thisX_isString && xIsString) {
+>thisX_isString && xIsString : boolean
+>thisX_isString : boolean
+>xIsString : boolean
+
+            let s: string;
+>s : string
+
+            s = this.x;
+>s = this.x : string | number
+>s : string
+>this.x : string | number
+>this : this
+>x : string | number
+
+            s = x;
+>s = x : string
+>s : string
+>x : string
+        }
+    }
+}
+
+class C11 {
+>C11 : C11
+
+    constructor(readonly x: string | number) {
+>x : string | number
+
+        const thisX_isString = typeof this.x === 'string';
+>thisX_isString : boolean
+>typeof this.x === 'string' : boolean
+>typeof this.x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
+>this.x : string | number
+>this : this
+>x : string | number
+>'string' : "string"
+
+        const xIsString = typeof x === 'string';
+>xIsString : boolean
+>typeof x === 'string' : boolean
+>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
+>x : string | number
+>'string' : "string"
+
+        if (thisX_isString && xIsString) {
+>thisX_isString && xIsString : boolean
+>thisX_isString : boolean
+>xIsString : boolean
+
+            // Some narrowings may be invalidated due to later assignments.
+            let s: string;
+>s : string
+
+            s = this.x;
+>s = this.x : string | number
+>s : string
+>this.x : string | number
+>this : this
+>x : string | number
+
+            s = x;
+>s = x : string | number
+>s : string
+>x : string | number
+        }
+        else {
+            this.x = 10;
+>this.x = 10 : 10
+>this.x : string | number
+>this : this
+>x : string | number
+>10 : 10
+
+            x = 10;
+>x = 10 : 10
+>x : string | number
+>10 : 10
+        }
+    }
+}
+
 // Mixing of aliased discriminants and conditionals
 
 function f40(obj: { kind: 'foo', foo?: string } | { kind: 'bar', bar?: number }) {