Skip to content

Commit 72da4b8

Browse files
charlespiercemhegazy
authored andcommitted
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
1 parent 94ea388 commit 72da4b8

6 files changed

+121
-1
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18314,6 +18314,12 @@ namespace ts {
1831418314
(kind & TypeFlags.NonPrimitive && isTypeAssignableTo(source, nonPrimitiveType));
1831518315
}
1831618316

18317+
function allTypesAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean): boolean {
18318+
return source.flags & TypeFlags.Union ?
18319+
every((source as UnionType).types, subType => allTypesAssignableToKind(subType, kind, strict)) :
18320+
isTypeAssignableToKind(source, kind, strict);
18321+
}
18322+
1831718323
function isConstEnumObjectType(type: Type): boolean {
1831818324
return getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && isConstEnumSymbol(type.symbol);
1831918325
}
@@ -18331,7 +18337,8 @@ namespace ts {
1833118337
// and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature.
1833218338
// The result is always of the Boolean primitive type.
1833318339
// NOTE: do not raise error if leftType is unknown as related error was already reported
18334-
if (!isTypeAny(leftType) && isTypeAssignableToKind(leftType, TypeFlags.Primitive)) {
18340+
if (!isTypeAny(leftType) &&
18341+
allTypesAssignableToKind(leftType, TypeFlags.Primitive)) {
1833518342
error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
1833618343
}
1833718344
// NOTE: do not raise error if right is unknown as related error was already reported
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
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.
3+
4+
5+
==== tests/cases/compiler/instanceofWithPrimitiveUnion.ts (2 errors) ====
6+
function test1(x: number | string) {
7+
if (x instanceof Object) {
8+
~
9+
!!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.
10+
x;
11+
}
12+
}
13+
14+
function test2(x: (number | string) | number) {
15+
if (x instanceof Object) {
16+
~
17+
!!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.
18+
x;
19+
}
20+
}
21+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [instanceofWithPrimitiveUnion.ts]
2+
function test1(x: number | string) {
3+
if (x instanceof Object) {
4+
x;
5+
}
6+
}
7+
8+
function test2(x: (number | string) | number) {
9+
if (x instanceof Object) {
10+
x;
11+
}
12+
}
13+
14+
15+
//// [instanceofWithPrimitiveUnion.js]
16+
function test1(x) {
17+
if (x instanceof Object) {
18+
x;
19+
}
20+
}
21+
function test2(x) {
22+
if (x instanceof Object) {
23+
x;
24+
}
25+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/compiler/instanceofWithPrimitiveUnion.ts ===
2+
function test1(x: number | string) {
3+
>test1 : Symbol(test1, Decl(instanceofWithPrimitiveUnion.ts, 0, 0))
4+
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 0, 15))
5+
6+
if (x instanceof Object) {
7+
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 0, 15))
8+
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
9+
10+
x;
11+
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 0, 15))
12+
}
13+
}
14+
15+
function test2(x: (number | string) | number) {
16+
>test2 : Symbol(test2, Decl(instanceofWithPrimitiveUnion.ts, 4, 1))
17+
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 6, 15))
18+
19+
if (x instanceof Object) {
20+
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 6, 15))
21+
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
22+
23+
x;
24+
>x : Symbol(x, Decl(instanceofWithPrimitiveUnion.ts, 6, 15))
25+
}
26+
}
27+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
=== tests/cases/compiler/instanceofWithPrimitiveUnion.ts ===
2+
function test1(x: number | string) {
3+
>test1 : (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+
16+
function test2(x: (number | string) | number) {
17+
>test2 : (x: string | number) => void
18+
>x : string | number
19+
20+
if (x instanceof Object) {
21+
>x instanceof Object : boolean
22+
>x : string | number
23+
>Object : ObjectConstructor
24+
25+
x;
26+
>x : string | number
27+
}
28+
}
29+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function test1(x: number | string) {
2+
if (x instanceof Object) {
3+
x;
4+
}
5+
}
6+
7+
function test2(x: (number | string) | number) {
8+
if (x instanceof Object) {
9+
x;
10+
}
11+
}

0 commit comments

Comments
 (0)