restore any narrowing
This commit is contained in:
parent
febda00f1b
commit
168c664639
|
@ -6356,9 +6356,6 @@ 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;
|
||||
|
@ -6372,6 +6369,14 @@ namespace ts {
|
|||
assumeTrue = !assumeTrue;
|
||||
}
|
||||
let typeInfo = primitiveTypeInfo[right.text];
|
||||
// If the type to be narrowed is any and we're affirmatively checking against a primitive, return the primitive
|
||||
if (!!(type.flags & TypeFlags.Any) && typeInfo && assumeTrue) {
|
||||
return typeInfo.type;
|
||||
}
|
||||
// At this point we can bail if it's not a union
|
||||
if (!(type.flags & TypeFlags.Union)) {
|
||||
return type;
|
||||
}
|
||||
let flags = typeInfo ? typeInfo.flags : (assumeTrue = !assumeTrue, TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol | TypeFlags.Boolean);
|
||||
let union = type as UnionType;
|
||||
if (assumeTrue) {
|
||||
|
|
49
tests/baselines/reference/typeGuardsWithAny.errors.txt
Normal file
49
tests/baselines/reference/typeGuardsWithAny.errors.txt
Normal file
|
@ -0,0 +1,49 @@
|
|||
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
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
=== 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))
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
=== 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