Skip to content

Commit 36df62d

Browse files
committed
Error when LHS of instanceof is Union of Primitives microsoft#18519
1 parent d23e5f1 commit 36df62d

6 files changed

+73
-1
lines changed

src/compiler/checker.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17604,7 +17604,9 @@ namespace ts {
1760417604
// and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature.
1760517605
// The result is always of the Boolean primitive type.
1760617606
// NOTE: do not raise error if leftType is unknown as related error was already reported
17607-
if (!isTypeAny(leftType) && isTypeAssignableToKind(leftType, TypeFlags.Primitive)) {
17607+
if (!isTypeAny(leftType) &&
17608+
(isTypeAssignableToKind(leftType, TypeFlags.Primitive) ||
17609+
isTypeUnionOfPrimitives(leftType))) {
1760817610
error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
1760917611
}
1761017612
// NOTE: do not raise error if right is unknown as related error was already reported
@@ -17617,6 +17619,16 @@ namespace ts {
1761717619
return booleanType;
1761817620
}
1761917621

17622+
function isTypeUnionOfPrimitives(source: Type) {
17623+
if (!(source.flags & TypeFlags.Union)) {
17624+
return false;
17625+
}
17626+
17627+
const unionTypes = (source as UnionType).types;
17628+
17629+
return every(unionTypes, subType => isTypeAssignableToKind(subType, TypeFlags.Primitive));
17630+
}
17631+
1762017632
function checkInExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type {
1762117633
if (leftType === silentNeverType || rightType === silentNeverType) {
1762217634
return silentNeverType;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
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.
2+
3+
4+
==== tests/cases/compiler/instanceofWithPrimitiveUnion.ts (1 errors) ====
5+
function foo(x: number | string) {
6+
if (x instanceof Object) {
7+
~
8+
!!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.
9+
x;
10+
}
11+
}
12+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//// [instanceofWithPrimitiveUnion.ts]
2+
function foo(x: number | string) {
3+
if (x instanceof Object) {
4+
x;
5+
}
6+
}
7+
8+
9+
//// [instanceofWithPrimitiveUnion.js]
10+
function foo(x) {
11+
if (x instanceof Object) {
12+
x;
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/compiler/instanceofWithPrimitiveUnion.ts ===
2+
function foo(x: number | string) {
3+
>foo : Symbol(foo, Decl(instanceofWithPrimitiveUnion.ts, 0, 0))
4+
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 0, 13))
5+
6+
if (x instanceof Object) {
7+
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 0, 13))
8+
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
9+
10+
x;
11+
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 0, 13))
12+
}
13+
}
14+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
=== tests/cases/compiler/instanceofWithPrimitiveUnion.ts ===
2+
function foo(x: number | string) {
3+
>foo : (x: string | number) => void
4+
>x : string | number
5+
6+
if (x instanceof Object) {
7+
>x instanceof Object : boolean
8+
>x : string | number
9+
>Object : ObjectConstructor
10+
11+
x;
12+
>x : string | number
13+
}
14+
}
15+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function foo(x: number | string) {
2+
if (x instanceof Object) {
3+
x;
4+
}
5+
}

0 commit comments

Comments
 (0)