Error when LHS of instanceof is Union of Primitives #18519 (#19063)

* Error when LHS of instanceof is Union of Primitives #18519

* Refactor to allTypesAssignableToKind method and update test

* Use ternary expression instead of if / else blocks
This commit is contained in:
Charles Pierce 2017-11-28 15:05:06 -08:00 committed by Mohamed Hegazy
parent 94ea38859b
commit 72da4b8f12
6 changed files with 121 additions and 1 deletions

View file

@ -18314,6 +18314,12 @@ namespace ts {
(kind & TypeFlags.NonPrimitive && isTypeAssignableTo(source, nonPrimitiveType));
}
function allTypesAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean): boolean {
return source.flags & TypeFlags.Union ?
every((source as UnionType).types, subType => allTypesAssignableToKind(subType, kind, strict)) :
isTypeAssignableToKind(source, kind, strict);
}
function isConstEnumObjectType(type: Type): boolean {
return getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && isConstEnumSymbol(type.symbol);
}
@ -18331,7 +18337,8 @@ namespace ts {
// and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature.
// The result is always of the Boolean primitive type.
// NOTE: do not raise error if leftType is unknown as related error was already reported
if (!isTypeAny(leftType) && isTypeAssignableToKind(leftType, TypeFlags.Primitive)) {
if (!isTypeAny(leftType) &&
allTypesAssignableToKind(leftType, TypeFlags.Primitive)) {
error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
}
// NOTE: do not raise error if right is unknown as related error was already reported

View file

@ -0,0 +1,21 @@
tests/cases/compiler/instanceofWithPrimitiveUnion.ts(2,9): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.
tests/cases/compiler/instanceofWithPrimitiveUnion.ts(8,9): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.
==== tests/cases/compiler/instanceofWithPrimitiveUnion.ts (2 errors) ====
function test1(x: number | string) {
if (x instanceof Object) {
~
!!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.
x;
}
}
function test2(x: (number | string) | number) {
if (x instanceof Object) {
~
!!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.
x;
}
}

View file

@ -0,0 +1,25 @@
//// [instanceofWithPrimitiveUnion.ts]
function test1(x: number | string) {
if (x instanceof Object) {
x;
}
}
function test2(x: (number | string) | number) {
if (x instanceof Object) {
x;
}
}
//// [instanceofWithPrimitiveUnion.js]
function test1(x) {
if (x instanceof Object) {
x;
}
}
function test2(x) {
if (x instanceof Object) {
x;
}
}

View file

@ -0,0 +1,27 @@
=== tests/cases/compiler/instanceofWithPrimitiveUnion.ts ===
function test1(x: number | string) {
>test1 : Symbol(test1, Decl(instanceofWithPrimitiveUnion.ts, 0, 0))
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 0, 15))
if (x instanceof Object) {
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 0, 15))
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
x;
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 0, 15))
}
}
function test2(x: (number | string) | number) {
>test2 : Symbol(test2, Decl(instanceofWithPrimitiveUnion.ts, 4, 1))
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 6, 15))
if (x instanceof Object) {
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 6, 15))
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
x;
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 6, 15))
}
}

View file

@ -0,0 +1,29 @@
=== tests/cases/compiler/instanceofWithPrimitiveUnion.ts ===
function test1(x: number | string) {
>test1 : (x: string | number) => void
>x : string | number
if (x instanceof Object) {
>x instanceof Object : boolean
>x : string | number
>Object : ObjectConstructor
x;
>x : string | number
}
}
function test2(x: (number | string) | number) {
>test2 : (x: string | number) => void
>x : string | number
if (x instanceof Object) {
>x instanceof Object : boolean
>x : string | number
>Object : ObjectConstructor
x;
>x : string | number
}
}

View file

@ -0,0 +1,11 @@
function test1(x: number | string) {
if (x instanceof Object) {
x;
}
}
function test2(x: (number | string) | number) {
if (x instanceof Object) {
x;
}
}