diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d3367776dec..c5bb5b31626 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -34353,6 +34353,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkExpressionWithTypeArguments(node: ExpressionWithTypeArguments | TypeQueryNode) { checkGrammarExpressionWithTypeArguments(node); forEach(node.typeArguments, checkSourceElement); + if (node.kind === SyntaxKind.ExpressionWithTypeArguments) { + const parent = walkUpParenthesizedExpressions(node.parent); + if (parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.InstanceOfKeyword && isNodeDescendantOf(node, (parent as BinaryExpression).right)) { + error(node, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_not_be_an_instantiation_expression); + } + } const exprType = node.kind === SyntaxKind.ExpressionWithTypeArguments ? checkExpression(node.expression) : isThisIdentifier(node.exprName) ? checkThisExpression(node.exprName) : checkExpression(node.exprName); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 4562b7e738e..dedb099abfa 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3615,6 +3615,10 @@ "category": "Error", "code": 2847 }, + "The right-hand side of an 'instanceof' expression must not be an instantiation expression.": { + "category": "Error", + "code": 2848 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/tests/baselines/reference/instanceofOnInstantiationExpression.errors.txt b/tests/baselines/reference/instanceofOnInstantiationExpression.errors.txt new file mode 100644 index 00000000000..54ec6dc4ed1 --- /dev/null +++ b/tests/baselines/reference/instanceofOnInstantiationExpression.errors.txt @@ -0,0 +1,29 @@ +tests/cases/compiler/instanceofOnInstantiationExpression.ts(10,21): error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression. +tests/cases/compiler/instanceofOnInstantiationExpression.ts(11,22): error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression. +tests/cases/compiler/instanceofOnInstantiationExpression.ts(12,23): error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression. + + +==== tests/cases/compiler/instanceofOnInstantiationExpression.ts (3 errors) ==== + declare class Box { + value: T; + } + + + declare const maybeBox: unknown; + + maybeBox instanceof Box; // OK + + maybeBox instanceof Box; // error + ~~~~~~~~~~~ +!!! error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression. + maybeBox instanceof (Box); // error + ~~~~~~~~~~~ +!!! error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression. + maybeBox instanceof ((Box)); // error + ~~~~~~~~~~~ +!!! error TS2848: The right-hand side of an 'instanceof' expression must not be an instantiation expression. + + Box instanceof Object; // OK + (Box) instanceof Object; // OK + ((Box)) instanceof Object; // OK + \ No newline at end of file diff --git a/tests/baselines/reference/instanceofOnInstantiationExpression.js b/tests/baselines/reference/instanceofOnInstantiationExpression.js new file mode 100644 index 00000000000..72e20ed5840 --- /dev/null +++ b/tests/baselines/reference/instanceofOnInstantiationExpression.js @@ -0,0 +1,27 @@ +//// [instanceofOnInstantiationExpression.ts] +declare class Box { + value: T; +} + + +declare const maybeBox: unknown; + +maybeBox instanceof Box; // OK + +maybeBox instanceof Box; // error +maybeBox instanceof (Box); // error +maybeBox instanceof ((Box)); // error + +Box instanceof Object; // OK +(Box) instanceof Object; // OK +((Box)) instanceof Object; // OK + + +//// [instanceofOnInstantiationExpression.js] +maybeBox instanceof Box; // OK +maybeBox instanceof (Box); // error +maybeBox instanceof (Box); // error +maybeBox instanceof ((Box)); // error +(Box) instanceof Object; // OK +(Box) instanceof Object; // OK +((Box)) instanceof Object; // OK diff --git a/tests/baselines/reference/instanceofOnInstantiationExpression.symbols b/tests/baselines/reference/instanceofOnInstantiationExpression.symbols new file mode 100644 index 00000000000..dc09a3b7625 --- /dev/null +++ b/tests/baselines/reference/instanceofOnInstantiationExpression.symbols @@ -0,0 +1,42 @@ +=== tests/cases/compiler/instanceofOnInstantiationExpression.ts === +declare class Box { +>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0)) +>T : Symbol(T, Decl(instanceofOnInstantiationExpression.ts, 0, 18)) + + value: T; +>value : Symbol(Box.value, Decl(instanceofOnInstantiationExpression.ts, 0, 22)) +>T : Symbol(T, Decl(instanceofOnInstantiationExpression.ts, 0, 18)) +} + + +declare const maybeBox: unknown; +>maybeBox : Symbol(maybeBox, Decl(instanceofOnInstantiationExpression.ts, 5, 13)) + +maybeBox instanceof Box; // OK +>maybeBox : Symbol(maybeBox, Decl(instanceofOnInstantiationExpression.ts, 5, 13)) +>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0)) + +maybeBox instanceof Box; // error +>maybeBox : Symbol(maybeBox, Decl(instanceofOnInstantiationExpression.ts, 5, 13)) +>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0)) + +maybeBox instanceof (Box); // error +>maybeBox : Symbol(maybeBox, Decl(instanceofOnInstantiationExpression.ts, 5, 13)) +>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0)) + +maybeBox instanceof ((Box)); // error +>maybeBox : Symbol(maybeBox, Decl(instanceofOnInstantiationExpression.ts, 5, 13)) +>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0)) + +Box instanceof Object; // OK +>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +(Box) instanceof Object; // OK +>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +((Box)) instanceof Object; // OK +>Box : Symbol(Box, Decl(instanceofOnInstantiationExpression.ts, 0, 0)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + diff --git a/tests/baselines/reference/instanceofOnInstantiationExpression.types b/tests/baselines/reference/instanceofOnInstantiationExpression.types new file mode 100644 index 00000000000..71642fdba79 --- /dev/null +++ b/tests/baselines/reference/instanceofOnInstantiationExpression.types @@ -0,0 +1,59 @@ +=== tests/cases/compiler/instanceofOnInstantiationExpression.ts === +declare class Box { +>Box : Box + + value: T; +>value : T +} + + +declare const maybeBox: unknown; +>maybeBox : unknown + +maybeBox instanceof Box; // OK +>maybeBox instanceof Box : boolean +>maybeBox : unknown +>Box : typeof Box + +maybeBox instanceof Box; // error +>maybeBox instanceof Box : boolean +>maybeBox : unknown +>Box : { new (): Box; prototype: Box; } +>Box : typeof Box + +maybeBox instanceof (Box); // error +>maybeBox instanceof (Box) : boolean +>maybeBox : unknown +>(Box) : { new (): Box; prototype: Box; } +>Box : { new (): Box; prototype: Box; } +>Box : typeof Box + +maybeBox instanceof ((Box)); // error +>maybeBox instanceof ((Box)) : boolean +>maybeBox : unknown +>((Box)) : { new (): Box; prototype: Box; } +>(Box) : { new (): Box; prototype: Box; } +>Box : { new (): Box; prototype: Box; } +>Box : typeof Box + +Box instanceof Object; // OK +>Box instanceof Object : boolean +>Box : { new (): Box; prototype: Box; } +>Box : typeof Box +>Object : ObjectConstructor + +(Box) instanceof Object; // OK +>(Box) instanceof Object : boolean +>(Box) : { new (): Box; prototype: Box; } +>Box : { new (): Box; prototype: Box; } +>Box : typeof Box +>Object : ObjectConstructor + +((Box)) instanceof Object; // OK +>((Box)) instanceof Object : boolean +>((Box)) : { new (): Box; prototype: Box; } +>(Box) : { new (): Box; prototype: Box; } +>Box : { new (): Box; prototype: Box; } +>Box : typeof Box +>Object : ObjectConstructor + diff --git a/tests/cases/compiler/instanceofOnInstantiationExpression.ts b/tests/cases/compiler/instanceofOnInstantiationExpression.ts new file mode 100644 index 00000000000..d1d12e45293 --- /dev/null +++ b/tests/cases/compiler/instanceofOnInstantiationExpression.ts @@ -0,0 +1,16 @@ +declare class Box { + value: T; +} + + +declare const maybeBox: unknown; + +maybeBox instanceof Box; // OK + +maybeBox instanceof Box; // error +maybeBox instanceof (Box); // error +maybeBox instanceof ((Box)); // error + +Box instanceof Object; // OK +(Box) instanceof Object; // OK +((Box)) instanceof Object; // OK