Improve type narrowing algorithm with typeof
This commit is contained in:
parent
062495c426
commit
febda00f1b
|
@ -6338,6 +6338,10 @@ namespace ts {
|
|||
// Stop at the first containing function or module declaration
|
||||
break loop;
|
||||
}
|
||||
// Preserve old top-level behavior - if the branch is really an empty set, revert to prior type
|
||||
if (narrowedType === getUnionType(emptyArray)) {
|
||||
narrowedType = type;
|
||||
}
|
||||
// Use narrowed type if construct contains no assignments to variable
|
||||
if (narrowedType !== type) {
|
||||
if (isVariableAssignedWithin(symbol, node)) {
|
||||
|
@ -6352,6 +6356,9 @@ namespace ts {
|
|||
return type;
|
||||
|
||||
function narrowTypeByEquality(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
|
||||
if (!(type.flags & TypeFlags.Union)) {
|
||||
return type;
|
||||
}
|
||||
// Check that we have 'typeof <symbol>' on the left and string literal on the right
|
||||
if (expr.left.kind !== SyntaxKind.TypeOfExpression || expr.right.kind !== SyntaxKind.StringLiteral) {
|
||||
return type;
|
||||
|
@ -6361,31 +6368,17 @@ namespace ts {
|
|||
if (left.expression.kind !== SyntaxKind.Identifier || getResolvedSymbol(<Identifier>left.expression) !== symbol) {
|
||||
return type;
|
||||
}
|
||||
let typeInfo = primitiveTypeInfo[right.text];
|
||||
if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken) {
|
||||
assumeTrue = !assumeTrue;
|
||||
}
|
||||
let typeInfo = primitiveTypeInfo[right.text];
|
||||
let flags = typeInfo ? typeInfo.flags : (assumeTrue = !assumeTrue, TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol | TypeFlags.Boolean);
|
||||
let union = type as UnionType;
|
||||
if (assumeTrue) {
|
||||
// Assumed result is true. If check was not for a primitive type, remove all primitive types
|
||||
if (!typeInfo) {
|
||||
return removeTypesFromUnionType(type, /*typeKind*/ TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.Boolean | TypeFlags.ESSymbol,
|
||||
/*isOfTypeKind*/ true, /*allowEmptyUnionResult*/ true);
|
||||
}
|
||||
// Check was for a primitive type, return that primitive type if it is a subtype
|
||||
if (isTypeSubtypeOf(typeInfo.type, type)) {
|
||||
return typeInfo.type;
|
||||
}
|
||||
// Otherwise, remove all types that aren't of the primitive type kind. This can happen when the type is
|
||||
// union of enum types and other types.
|
||||
return removeTypesFromUnionType(type, /*typeKind*/ typeInfo.flags, /*isOfTypeKind*/ false, /*allowEmptyUnionResult*/ true);
|
||||
return getUnionType(filter(union.types, t => !!(t.flags & flags)));
|
||||
}
|
||||
else {
|
||||
// Assumed result is false. If check was for a primitive type, remove that primitive type
|
||||
if (typeInfo) {
|
||||
return removeTypesFromUnionType(type, /*typeKind*/ typeInfo.flags, /*isOfTypeKind*/ true, /*allowEmptyUnionResult*/ true);
|
||||
}
|
||||
// Otherwise we don't have enough information to do anything.
|
||||
return type;
|
||||
return getUnionType(filter(union.types, t => !(t.flags & flags)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6399,7 +6392,7 @@ namespace ts {
|
|||
// and the second operand was false. We narrow with those assumptions and union the two resulting types.
|
||||
return getUnionType([
|
||||
narrowType(type, expr.left, /*assumeTrue*/ false),
|
||||
narrowType(narrowType(type, expr.left, /*assumeTrue*/ true), expr.right, /*assumeTrue*/ false)
|
||||
narrowType(type, expr.right, /*assumeTrue*/ false)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -6410,7 +6403,7 @@ namespace ts {
|
|||
// and the second operand was true. We narrow with those assumptions and union the two resulting types.
|
||||
return getUnionType([
|
||||
narrowType(type, expr.left, /*assumeTrue*/ true),
|
||||
narrowType(narrowType(type, expr.left, /*assumeTrue*/ false), expr.right, /*assumeTrue*/ true)
|
||||
narrowType(type, expr.right, /*assumeTrue*/ true)
|
||||
]);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -21,5 +21,5 @@ if (typeof x === "object") {
|
|||
}
|
||||
else {
|
||||
x;
|
||||
>x : symbol | Foo
|
||||
>x : symbol
|
||||
}
|
||||
|
|
11
tests/baselines/reference/typeGuardNesting.js
Normal file
11
tests/baselines/reference/typeGuardNesting.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
//// [typeGuardNesting.ts]
|
||||
let strOrBool: string|boolean;
|
||||
if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') {
|
||||
var label: string = (typeof strOrBool === 'string') ? strOrBool : "other string";
|
||||
}
|
||||
|
||||
//// [typeGuardNesting.js]
|
||||
var strOrBool;
|
||||
if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') {
|
||||
var label = (typeof strOrBool === 'string') ? strOrBool : "other string";
|
||||
}
|
14
tests/baselines/reference/typeGuardNesting.symbols
Normal file
14
tests/baselines/reference/typeGuardNesting.symbols
Normal file
|
@ -0,0 +1,14 @@
|
|||
=== tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts ===
|
||||
let strOrBool: string|boolean;
|
||||
>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3))
|
||||
|
||||
if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') {
|
||||
>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3))
|
||||
>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3))
|
||||
>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3))
|
||||
|
||||
var label: string = (typeof strOrBool === 'string') ? strOrBool : "other string";
|
||||
>label : Symbol(label, Decl(typeGuardNesting.ts, 2, 4))
|
||||
>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3))
|
||||
>strOrBool : Symbol(strOrBool, Decl(typeGuardNesting.ts, 0, 3))
|
||||
}
|
30
tests/baselines/reference/typeGuardNesting.types
Normal file
30
tests/baselines/reference/typeGuardNesting.types
Normal file
|
@ -0,0 +1,30 @@
|
|||
=== tests/cases/conformance/expressions/typeGuards/typeGuardNesting.ts ===
|
||||
let strOrBool: string|boolean;
|
||||
>strOrBool : string | boolean
|
||||
|
||||
if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string') {
|
||||
>(typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'string' : boolean
|
||||
>(typeof strOrBool === 'boolean' && !strOrBool) : boolean
|
||||
>typeof strOrBool === 'boolean' && !strOrBool : boolean
|
||||
>typeof strOrBool === 'boolean' : boolean
|
||||
>typeof strOrBool : string
|
||||
>strOrBool : string | boolean
|
||||
>'boolean' : string
|
||||
>!strOrBool : boolean
|
||||
>strOrBool : boolean
|
||||
>typeof strOrBool === 'string' : boolean
|
||||
>typeof strOrBool : string
|
||||
>strOrBool : string | boolean
|
||||
>'string' : string
|
||||
|
||||
var label: string = (typeof strOrBool === 'string') ? strOrBool : "other string";
|
||||
>label : string
|
||||
>(typeof strOrBool === 'string') ? strOrBool : "other string" : string
|
||||
>(typeof strOrBool === 'string') : boolean
|
||||
>typeof strOrBool === 'string' : boolean
|
||||
>typeof strOrBool : string
|
||||
>strOrBool : boolean | string
|
||||
>'string' : string
|
||||
>strOrBool : string
|
||||
>"other string" : string
|
||||
}
|
|
@ -63,7 +63,7 @@ else {
|
|||
var r2: string | C = strOrC; // string | C
|
||||
>r2 : string | C
|
||||
>C : C
|
||||
>strOrC : string | C
|
||||
>strOrC : string
|
||||
}
|
||||
if (typeof numOrC === "Object") {
|
||||
>typeof numOrC === "Object" : boolean
|
||||
|
@ -80,7 +80,7 @@ else {
|
|||
var r3: number | C = numOrC; // number | C
|
||||
>r3 : number | C
|
||||
>C : C
|
||||
>numOrC : number | C
|
||||
>numOrC : number
|
||||
}
|
||||
if (typeof boolOrC === "Object") {
|
||||
>typeof boolOrC === "Object" : boolean
|
||||
|
@ -97,7 +97,7 @@ else {
|
|||
var r4: boolean | C = boolOrC; // boolean | C
|
||||
>r4 : boolean | C
|
||||
>C : C
|
||||
>boolOrC : boolean | C
|
||||
>boolOrC : boolean
|
||||
}
|
||||
|
||||
// Narrowing occurs only if target type is a subtype of variable type
|
||||
|
@ -129,7 +129,7 @@ if (typeof strOrC !== "Object") {
|
|||
var r2: string | C = strOrC; // string | C
|
||||
>r2 : string | C
|
||||
>C : C
|
||||
>strOrC : string | C
|
||||
>strOrC : string
|
||||
}
|
||||
else {
|
||||
c = strOrC; // C
|
||||
|
@ -146,7 +146,7 @@ if (typeof numOrC !== "Object") {
|
|||
var r3: number | C = numOrC; // number | C
|
||||
>r3 : number | C
|
||||
>C : C
|
||||
>numOrC : number | C
|
||||
>numOrC : number
|
||||
}
|
||||
else {
|
||||
c = numOrC; // C
|
||||
|
@ -163,7 +163,7 @@ if (typeof boolOrC !== "Object") {
|
|||
var r4: boolean | C = boolOrC; // boolean | C
|
||||
>r4 : boolean | C
|
||||
>C : C
|
||||
>boolOrC : boolean | C
|
||||
>boolOrC : boolean
|
||||
}
|
||||
else {
|
||||
c = boolOrC; // C
|
||||
|
|
17
tests/baselines/reference/typeGuardRedundancy.js
Normal file
17
tests/baselines/reference/typeGuardRedundancy.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
//// [typeGuardRedundancy.ts]
|
||||
var x: string|number;
|
||||
|
||||
var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed;
|
||||
|
||||
var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr;
|
||||
|
||||
var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed;
|
||||
|
||||
var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr;
|
||||
|
||||
//// [typeGuardRedundancy.js]
|
||||
var x;
|
||||
var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed;
|
||||
var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr;
|
||||
var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed;
|
||||
var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr;
|
48
tests/baselines/reference/typeGuardRedundancy.symbols
Normal file
48
tests/baselines/reference/typeGuardRedundancy.symbols
Normal file
|
@ -0,0 +1,48 @@
|
|||
=== tests/cases/conformance/expressions/typeGuards/typeGuardRedundancy.ts ===
|
||||
var x: string|number;
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
|
||||
var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed;
|
||||
>r1 : Symbol(r1, Decl(typeGuardRedundancy.ts, 2, 3))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>substr : Symbol(String.substr, Decl(lib.d.ts, --, --))
|
||||
>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
|
||||
var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr;
|
||||
>r2 : Symbol(r2, Decl(typeGuardRedundancy.ts, 4, 3))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>substr : Symbol(String.substr, Decl(lib.d.ts, --, --))
|
||||
|
||||
var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed;
|
||||
>r3 : Symbol(r3, Decl(typeGuardRedundancy.ts, 6, 3))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>substr : Symbol(String.substr, Decl(lib.d.ts, --, --))
|
||||
>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
|
||||
var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr;
|
||||
>r4 : Symbol(r4, Decl(typeGuardRedundancy.ts, 8, 3))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --))
|
||||
>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(typeGuardRedundancy.ts, 0, 3))
|
||||
>substr : Symbol(String.substr, Decl(lib.d.ts, --, --))
|
||||
|
84
tests/baselines/reference/typeGuardRedundancy.types
Normal file
84
tests/baselines/reference/typeGuardRedundancy.types
Normal file
|
@ -0,0 +1,84 @@
|
|||
=== tests/cases/conformance/expressions/typeGuards/typeGuardRedundancy.ts ===
|
||||
var x: string|number;
|
||||
>x : string | number
|
||||
|
||||
var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed;
|
||||
>r1 : (from: number, length?: number) => string
|
||||
>typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed : (from: number, length?: number) => string
|
||||
>typeof x === "string" && typeof x === "string" : boolean
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string
|
||||
>"string" : string
|
||||
>x.substr : (from: number, length?: number) => string
|
||||
>x : string
|
||||
>substr : (from: number, length?: number) => string
|
||||
>x.toFixed : (fractionDigits?: number) => string
|
||||
>x : number
|
||||
>toFixed : (fractionDigits?: number) => string
|
||||
|
||||
var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr;
|
||||
>r2 : (fractionDigits?: number) => string
|
||||
>!(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr : (fractionDigits?: number) => string
|
||||
>!(typeof x === "string" && typeof x === "string") : boolean
|
||||
>(typeof x === "string" && typeof x === "string") : boolean
|
||||
>typeof x === "string" && typeof x === "string" : boolean
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string
|
||||
>"string" : string
|
||||
>x.toFixed : (fractionDigits?: number) => string
|
||||
>x : number
|
||||
>toFixed : (fractionDigits?: number) => string
|
||||
>x.substr : (from: number, length?: number) => string
|
||||
>x : string
|
||||
>substr : (from: number, length?: number) => string
|
||||
|
||||
var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed;
|
||||
>r3 : (from: number, length?: number) => string
|
||||
>typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed : (from: number, length?: number) => string
|
||||
>typeof x === "string" || typeof x === "string" : boolean
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : number
|
||||
>"string" : string
|
||||
>x.substr : (from: number, length?: number) => string
|
||||
>x : string
|
||||
>substr : (from: number, length?: number) => string
|
||||
>x.toFixed : (fractionDigits?: number) => string
|
||||
>x : number
|
||||
>toFixed : (fractionDigits?: number) => string
|
||||
|
||||
var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr;
|
||||
>r4 : (fractionDigits?: number) => string
|
||||
>!(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr : (fractionDigits?: number) => string
|
||||
>!(typeof x === "string" || typeof x === "string") : boolean
|
||||
>(typeof x === "string" || typeof x === "string") : boolean
|
||||
>typeof x === "string" || typeof x === "string" : boolean
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : number
|
||||
>"string" : string
|
||||
>x.toFixed : (fractionDigits?: number) => string
|
||||
>x : number
|
||||
>toFixed : (fractionDigits?: number) => string
|
||||
>x.substr : (from: number, length?: number) => string
|
||||
>x : string
|
||||
>substr : (from: number, length?: number) => string
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(11,7): error TS2339: Property 'p' does not exist on type 'string'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(18,7): error TS2339: Property 'p' does not exist on type 'number'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(25,7): error TS2339: Property 'p' does not exist on type 'boolean'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts (3 errors) ====
|
||||
var x: any = { p: 0 };
|
||||
|
||||
if (x instanceof Object) {
|
||||
x.p; // No error, type any unaffected by instanceof type guard
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type any unaffected by instanceof type guard
|
||||
}
|
||||
|
||||
if (typeof x === "string") {
|
||||
x.p; // Error, type any narrowed by primitive type check
|
||||
~
|
||||
!!! error TS2339: Property 'p' does not exist on type 'string'.
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
}
|
||||
|
||||
if (typeof x === "number") {
|
||||
x.p; // Error, type any narrowed by primitive type check
|
||||
~
|
||||
!!! error TS2339: Property 'p' does not exist on type 'number'.
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
}
|
||||
|
||||
if (typeof x === "boolean") {
|
||||
x.p; // Error, type any narrowed by primitive type check
|
||||
~
|
||||
!!! error TS2339: Property 'p' does not exist on type 'boolean'.
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
}
|
||||
|
||||
if (typeof x === "object") {
|
||||
x.p; // No error, type any only affected by primitive type check
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
}
|
||||
|
61
tests/baselines/reference/typeGuardsWithAny.symbols
Normal file
61
tests/baselines/reference/typeGuardsWithAny.symbols
Normal file
|
@ -0,0 +1,61 @@
|
|||
=== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts ===
|
||||
var x: any = { p: 0 };
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
>p : Symbol(p, Decl(typeGuardsWithAny.ts, 0, 14))
|
||||
|
||||
if (x instanceof Object) {
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
x.p; // No error, type any unaffected by instanceof type guard
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type any unaffected by instanceof type guard
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
}
|
||||
|
||||
if (typeof x === "string") {
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
|
||||
x.p; // Error, type any narrowed by primitive type check
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
}
|
||||
|
||||
if (typeof x === "number") {
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
|
||||
x.p; // Error, type any narrowed by primitive type check
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
}
|
||||
|
||||
if (typeof x === "boolean") {
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
|
||||
x.p; // Error, type any narrowed by primitive type check
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
}
|
||||
|
||||
if (typeof x === "object") {
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
|
||||
x.p; // No error, type any only affected by primitive type check
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
>x : Symbol(x, Decl(typeGuardsWithAny.ts, 0, 3))
|
||||
}
|
||||
|
96
tests/baselines/reference/typeGuardsWithAny.types
Normal file
96
tests/baselines/reference/typeGuardsWithAny.types
Normal file
|
@ -0,0 +1,96 @@
|
|||
=== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts ===
|
||||
var x: any = { p: 0 };
|
||||
>x : any
|
||||
>{ p: 0 } : { p: number; }
|
||||
>p : number
|
||||
>0 : number
|
||||
|
||||
if (x instanceof Object) {
|
||||
>x instanceof Object : boolean
|
||||
>x : any
|
||||
>Object : ObjectConstructor
|
||||
|
||||
x.p; // No error, type any unaffected by instanceof type guard
|
||||
>x.p : any
|
||||
>x : any
|
||||
>p : any
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type any unaffected by instanceof type guard
|
||||
>x.p : any
|
||||
>x : any
|
||||
>p : any
|
||||
}
|
||||
|
||||
if (typeof x === "string") {
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : any
|
||||
>"string" : string
|
||||
|
||||
x.p; // Error, type any narrowed by primitive type check
|
||||
>x.p : any
|
||||
>x : any
|
||||
>p : any
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
>x.p : any
|
||||
>x : any
|
||||
>p : any
|
||||
}
|
||||
|
||||
if (typeof x === "number") {
|
||||
>typeof x === "number" : boolean
|
||||
>typeof x : string
|
||||
>x : any
|
||||
>"number" : string
|
||||
|
||||
x.p; // Error, type any narrowed by primitive type check
|
||||
>x.p : any
|
||||
>x : any
|
||||
>p : any
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
>x.p : any
|
||||
>x : any
|
||||
>p : any
|
||||
}
|
||||
|
||||
if (typeof x === "boolean") {
|
||||
>typeof x === "boolean" : boolean
|
||||
>typeof x : string
|
||||
>x : any
|
||||
>"boolean" : string
|
||||
|
||||
x.p; // Error, type any narrowed by primitive type check
|
||||
>x.p : any
|
||||
>x : any
|
||||
>p : any
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
>x.p : any
|
||||
>x : any
|
||||
>p : any
|
||||
}
|
||||
|
||||
if (typeof x === "object") {
|
||||
>typeof x === "object" : boolean
|
||||
>typeof x : string
|
||||
>x : any
|
||||
>"object" : string
|
||||
|
||||
x.p; // No error, type any only affected by primitive type check
|
||||
>x.p : any
|
||||
>x : any
|
||||
>p : any
|
||||
}
|
||||
else {
|
||||
x.p; // No error, type unaffected in this branch
|
||||
>x.p : any
|
||||
>x : any
|
||||
>p : any
|
||||
}
|
||||
|
Loading…
Reference in a new issue