mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Fix constant reference check in CFA (#44762)
* Check entire access path is constant when narrowing by inlining * Add tests * Accept new baselines * Added test cases for parameter properties. * Accepted baselines. Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
This commit is contained in:
co-authored by
Daniel Rosenwasser
parent
c0d5c29080
commit
5f8a9e5181
+21
-8
@@ -23018,7 +23018,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;
|
||||
@@ -24063,11 +24076,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--;
|
||||
@@ -24413,12 +24426,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
|
||||
@@ -24433,7 +24446,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.
|
||||
@@ -27652,7 +27665,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
|
||||
|
||||
@@ -1,30 +1,40 @@
|
||||
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; }'.
|
||||
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; }'.
|
||||
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; }'.
|
||||
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; }'.
|
||||
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; }'.
|
||||
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; }'.
|
||||
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; }'.
|
||||
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; }'.
|
||||
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; }'.
|
||||
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; }'.
|
||||
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(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(210,13): error TS2322: Type 'string | number' is not assignable to type 'number'.
|
||||
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(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(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(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(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(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(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(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(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(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(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(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 (12 errors) ====
|
||||
==== tests/cases/conformance/controlFlow/controlFlowAliasing.ts (17 errors) ====
|
||||
// Narrowing by aliased conditional expressions
|
||||
|
||||
function f10(x: string | number) {
|
||||
@@ -72,6 +82,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) {
|
||||
@@ -236,6 +282,45 @@ tests/cases/conformance/controlFlow/controlFlowAliasing.ts(210,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 }) {
|
||||
|
||||
@@ -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) {
|
||||
@@ -180,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 }) {
|
||||
@@ -256,6 +316,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) {
|
||||
@@ -380,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;
|
||||
@@ -413,6 +530,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;
|
||||
@@ -508,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;
|
||||
|
||||
@@ -112,90 +112,97 @@ function f14(x: number | null | undefined): number | null {
|
||||
>x : Symbol(x, Decl(controlFlowAliasing.ts, 42, 13))
|
||||
}
|
||||
|
||||
function f15(obj: { readonly x: string | number }) {
|
||||
>f15 : Symbol(f15, Decl(controlFlowAliasing.ts, 45, 1))
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 47, 13))
|
||||
>x : Symbol(x, Decl(controlFlowAliasing.ts, 47, 19))
|
||||
|
||||
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))
|
||||
>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, 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))
|
||||
|
||||
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))
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 47, 13))
|
||||
>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 47, 19), Decl(controlFlowAliasing.ts, 47, 50))
|
||||
|
||||
if (isFoo) {
|
||||
>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 48, 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))
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
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))
|
||||
|
||||
if (isFoo) {
|
||||
>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 58, 9))
|
||||
|
||||
obj.foo; // Not narrowed because isFoo has type annotation
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 57, 13))
|
||||
}
|
||||
else {
|
||||
obj.bar; // Not narrowed because isFoo has type annotation
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 57, 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))
|
||||
|
||||
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))
|
||||
|
||||
if (isFoo) {
|
||||
>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 68, 7))
|
||||
|
||||
obj.foo; // Not narrowed because isFoo is mutable
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 67, 13))
|
||||
}
|
||||
else {
|
||||
obj.bar; // Not narrowed because isFoo is mutable
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 67, 13))
|
||||
}
|
||||
}
|
||||
|
||||
function f23(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
|
||||
>f23 : Symbol(f23, Decl(controlFlowAliasing.ts, 75, 1))
|
||||
>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))
|
||||
@@ -208,395 +215,560 @@ function f23(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
|
||||
>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 77, 19), Decl(controlFlowAliasing.ts, 77, 50))
|
||||
|
||||
obj = obj;
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 77, 13))
|
||||
|
||||
if (isFoo) {
|
||||
>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 78, 9))
|
||||
|
||||
obj.foo; // Not narrowed because obj is assigned in function body
|
||||
obj.foo;
|
||||
>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, 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, 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, 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, 88, 9))
|
||||
|
||||
obj.foo; // Not narrowed because isFoo has type annotation
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 87, 13))
|
||||
}
|
||||
else {
|
||||
obj.bar; // Not narrowed because isFoo has type annotation
|
||||
>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, 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, 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, 98, 7))
|
||||
|
||||
obj.foo; // Not narrowed because isFoo is mutable
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 97, 13))
|
||||
}
|
||||
else {
|
||||
obj.bar; // Not narrowed because isFoo is mutable
|
||||
>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, 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, 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, 107, 13))
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 107, 13))
|
||||
|
||||
if (isFoo) {
|
||||
>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, 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))
|
||||
|
||||
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))
|
||||
|
||||
if (kind === 'foo') {
|
||||
>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 144, 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))
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
const { kind } = obj;
|
||||
>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 154, 11))
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 153, 13))
|
||||
|
||||
if (kind === 'foo') {
|
||||
>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 154, 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))
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
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))
|
||||
|
||||
if (k === 'foo') {
|
||||
>k : Symbol(k, Decl(controlFlowAliasing.ts, 164, 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))
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
function f33(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
|
||||
>f33 : Symbol(f33, Decl(controlFlowAliasing.ts, 171, 1))
|
||||
>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 : Symbol(kind, Decl(controlFlowAliasing.ts, 174, 11))
|
||||
const kind = obj.kind;
|
||||
>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))
|
||||
|
||||
switch (kind) {
|
||||
>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 174, 11))
|
||||
if (kind === 'foo') {
|
||||
>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 174, 9))
|
||||
|
||||
case 'foo': obj.foo; break;
|
||||
obj.foo;
|
||||
>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))
|
||||
|
||||
case 'bar': obj.bar; break;
|
||||
}
|
||||
else {
|
||||
obj.bar;
|
||||
>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))
|
||||
}
|
||||
}
|
||||
|
||||
// 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))
|
||||
function f31(obj: { kind: 'foo', foo: string } | { kind: 'bar', bar: number }) {
|
||||
>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, 51))
|
||||
>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 183, 64))
|
||||
>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, 184, 11))
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 183, 13))
|
||||
|
||||
const isFoo = kind == 'foo';
|
||||
>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 185, 9))
|
||||
if (kind === 'foo') {
|
||||
>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 184, 11))
|
||||
|
||||
if (isFoo && obj.foo) {
|
||||
>isFoo : Symbol(isFoo, Decl(controlFlowAliasing.ts, 185, 9))
|
||||
obj.foo;
|
||||
>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, 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, 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, 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, 194, 11))
|
||||
|
||||
obj.foo;
|
||||
>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, 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, 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, 204, 11))
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 203, 13))
|
||||
|
||||
switch (kind) {
|
||||
>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 204, 11))
|
||||
|
||||
case 'foo': obj.foo; break;
|
||||
>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, 203, 63))
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 203, 13))
|
||||
>bar : Symbol(bar, Decl(controlFlowAliasing.ts, 203, 63))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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, 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, 244, 11))
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 243, 13))
|
||||
|
||||
const isFoo = kind == 'foo';
|
||||
>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, 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, 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, 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, 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, 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, 193, 80))
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 195, 13))
|
||||
>Data : Symbol(Data, Decl(controlFlowAliasing.ts, 189, 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, 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, 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, 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, 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, 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, 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, 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, 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, 204, 14))
|
||||
>kind : Symbol(kind, Decl(controlFlowAliasing.ts, 264, 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, 266, 11))
|
||||
>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 264, 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, 269, 11))
|
||||
>payload : Symbol(payload, Decl(controlFlowAliasing.ts, 264, 20))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
@@ -590,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 }) {
|
||||
|
||||
@@ -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) {
|
||||
@@ -182,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 }) {
|
||||
|
||||
Reference in New Issue
Block a user