Skip to content

Commit b7b0b52

Browse files
authored
Disallow instantiation expressions on the right side of instanceof (microsoft#53323)
1 parent b1ef5b7 commit b7b0b52

7 files changed

+183
-0
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34353,6 +34353,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3435334353
function checkExpressionWithTypeArguments(node: ExpressionWithTypeArguments | TypeQueryNode) {
3435434354
checkGrammarExpressionWithTypeArguments(node);
3435534355
forEach(node.typeArguments, checkSourceElement);
34356+
if (node.kind === SyntaxKind.ExpressionWithTypeArguments) {
34357+
const parent = walkUpParenthesizedExpressions(node.parent);
34358+
if (parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.InstanceOfKeyword && isNodeDescendantOf(node, (parent as BinaryExpression).right)) {
34359+
error(node, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_not_be_an_instantiation_expression);
34360+
}
34361+
}
3435634362
const exprType = node.kind === SyntaxKind.ExpressionWithTypeArguments ? checkExpression(node.expression) :
3435734363
isThisIdentifier(node.exprName) ? checkThisExpression(node.exprName) :
3435834364
checkExpression(node.exprName);

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3615,6 +3615,10 @@
36153615
"category": "Error",
36163616
"code": 2847
36173617
},
3618+
"The right-hand side of an 'instanceof' expression must not be an instantiation expression.": {
3619+
"category": "Error",
3620+
"code": 2848
3621+
},
36183622

36193623
"Import declaration '{0}' is using private name '{1}'.": {
36203624
"category": "Error",
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
tests/cases/compiler/instanceofOnInstantiationExpression.ts(10,21): error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression.
2+
tests/cases/compiler/instanceofOnInstantiationExpression.ts(11,22): error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression.
3+
tests/cases/compiler/instanceofOnInstantiationExpression.ts(12,23): error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression.
4+
5+
6+
==== tests/cases/compiler/instanceofOnInstantiationExpression.ts (3 errors) ====
7+
declare class Box<T> {
8+
value: T;
9+
}
10+
11+
12+
declare const maybeBox: unknown;
13+
14+
maybeBox instanceof Box; // OK
15+
16+
maybeBox instanceof Box<number>; // error
17+
~~~~~~~~~~~
18+
!!! error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression.
19+
maybeBox instanceof (Box<number>); // error
20+
~~~~~~~~~~~
21+
!!! error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression.
22+
maybeBox instanceof ((Box<number>)); // error
23+
~~~~~~~~~~~
24+
!!! error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression.
25+
26+
Box<number> instanceof Object; // OK
27+
(Box<number>) instanceof Object; // OK
28+
((Box<number>)) instanceof Object; // OK
29+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//// [instanceofOnInstantiationExpression.ts]
2+
declare class Box<T> {
3+
value: T;
4+
}
5+
6+
7+
declare const maybeBox: unknown;
8+
9+
maybeBox instanceof Box; // OK
10+
11+
maybeBox instanceof Box<number>; // error
12+
maybeBox instanceof (Box<number>); // error
13+
maybeBox instanceof ((Box<number>)); // error
14+
15+
Box<number> instanceof Object; // OK
16+
(Box<number>) instanceof Object; // OK
17+
((Box<number>)) instanceof Object; // OK
18+
19+
20+
//// [instanceofOnInstantiationExpression.js]
21+
maybeBox instanceof Box; // OK
22+
maybeBox instanceof (Box); // error
23+
maybeBox instanceof (Box); // error
24+
maybeBox instanceof ((Box)); // error
25+
(Box) instanceof Object; // OK
26+
(Box) instanceof Object; // OK
27+
((Box)) instanceof Object; // OK
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
=== tests/cases/compiler/instanceofOnInstantiationExpression.ts ===
2+
declare class Box<T> {
3+
>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0))
4+
>T : Symbol(T, Decl(instanceofOnInstantiationExpression.ts, 0, 18))
5+
6+
value: T;
7+
>value : Symbol(Box.value, Decl(instanceofOnInstantiationExpression.ts, 0, 22))
8+
>T : Symbol(T, Decl(instanceofOnInstantiationExpression.ts, 0, 18))
9+
}
10+
11+
12+
declare const maybeBox: unknown;
13+
>maybeBox : Symbol(maybeBox, Decl(instanceofOnInstantiationExpression.ts, 5, 13))
14+
15+
maybeBox instanceof Box; // OK
16+
>maybeBox : Symbol(maybeBox, Decl(instanceofOnInstantiationExpression.ts, 5, 13))
17+
>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0))
18+
19+
maybeBox instanceof Box<number>; // error
20+
>maybeBox : Symbol(maybeBox, Decl(instanceofOnInstantiationExpression.ts, 5, 13))
21+
>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0))
22+
23+
maybeBox instanceof (Box<number>); // error
24+
>maybeBox : Symbol(maybeBox, Decl(instanceofOnInstantiationExpression.ts, 5, 13))
25+
>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0))
26+
27+
maybeBox instanceof ((Box<number>)); // error
28+
>maybeBox : Symbol(maybeBox, Decl(instanceofOnInstantiationExpression.ts, 5, 13))
29+
>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0))
30+
31+
Box<number> instanceof Object; // OK
32+
>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0))
33+
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
34+
35+
(Box<number>) instanceof Object; // OK
36+
>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0))
37+
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
38+
39+
((Box<number>)) instanceof Object; // OK
40+
>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0))
41+
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
42+
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
=== tests/cases/compiler/instanceofOnInstantiationExpression.ts ===
2+
declare class Box<T> {
3+
>Box : Box<T>
4+
5+
value: T;
6+
>value : T
7+
}
8+
9+
10+
declare const maybeBox: unknown;
11+
>maybeBox : unknown
12+
13+
maybeBox instanceof Box; // OK
14+
>maybeBox instanceof Box : boolean
15+
>maybeBox : unknown
16+
>Box : typeof Box
17+
18+
maybeBox instanceof Box<number>; // error
19+
>maybeBox instanceof Box<number> : boolean
20+
>maybeBox : unknown
21+
>Box<number> : { new (): Box<number>; prototype: Box<any>; }
22+
>Box : typeof Box
23+
24+
maybeBox instanceof (Box<number>); // error
25+
>maybeBox instanceof (Box<number>) : boolean
26+
>maybeBox : unknown
27+
>(Box<number>) : { new (): Box<number>; prototype: Box<any>; }
28+
>Box<number> : { new (): Box<number>; prototype: Box<any>; }
29+
>Box : typeof Box
30+
31+
maybeBox instanceof ((Box<number>)); // error
32+
>maybeBox instanceof ((Box<number>)) : boolean
33+
>maybeBox : unknown
34+
>((Box<number>)) : { new (): Box<number>; prototype: Box<any>; }
35+
>(Box<number>) : { new (): Box<number>; prototype: Box<any>; }
36+
>Box<number> : { new (): Box<number>; prototype: Box<any>; }
37+
>Box : typeof Box
38+
39+
Box<number> instanceof Object; // OK
40+
>Box<number> instanceof Object : boolean
41+
>Box<number> : { new (): Box<number>; prototype: Box<any>; }
42+
>Box : typeof Box
43+
>Object : ObjectConstructor
44+
45+
(Box<number>) instanceof Object; // OK
46+
>(Box<number>) instanceof Object : boolean
47+
>(Box<number>) : { new (): Box<number>; prototype: Box<any>; }
48+
>Box<number> : { new (): Box<number>; prototype: Box<any>; }
49+
>Box : typeof Box
50+
>Object : ObjectConstructor
51+
52+
((Box<number>)) instanceof Object; // OK
53+
>((Box<number>)) instanceof Object : boolean
54+
>((Box<number>)) : { new (): Box<number>; prototype: Box<any>; }
55+
>(Box<number>) : { new (): Box<number>; prototype: Box<any>; }
56+
>Box<number> : { new (): Box<number>; prototype: Box<any>; }
57+
>Box : typeof Box
58+
>Object : ObjectConstructor
59+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
declare class Box<T> {
2+
value: T;
3+
}
4+
5+
6+
declare const maybeBox: unknown;
7+
8+
maybeBox instanceof Box; // OK
9+
10+
maybeBox instanceof Box<number>; // error
11+
maybeBox instanceof (Box<number>); // error
12+
maybeBox instanceof ((Box<number>)); // error
13+
14+
Box<number> instanceof Object; // OK
15+
(Box<number>) instanceof Object; // OK
16+
((Box<number>)) instanceof Object; // OK

0 commit comments

Comments
 (0)