Skip to content

Commit 5b075ff

Browse files
authored
Merge pull request #12728 from Microsoft/instanceof-requires-callable-rhs
Instanceof requires callable or constructable right-hand side
2 parents e9e7fce + f15a7a3 commit 5b075ff

File tree

5 files changed

+164
-2
lines changed

5 files changed

+164
-2
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14586,14 +14586,18 @@ namespace ts {
1458614586
}
1458714587
// TypeScript 1.0 spec (April 2014): 4.15.4
1458814588
// The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type,
14589-
// and the right operand to be of type Any or a subtype of the 'Function' interface type.
14589+
// and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature.
1459014590
// The result is always of the Boolean primitive type.
1459114591
// NOTE: do not raise error if leftType is unknown as related error was already reported
1459214592
if (isTypeOfKind(leftType, TypeFlags.Primitive)) {
1459314593
error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
1459414594
}
1459514595
// NOTE: do not raise error if right is unknown as related error was already reported
14596-
if (!(isTypeAny(rightType) || isTypeSubtypeOf(rightType, globalFunctionType))) {
14596+
if (!(isTypeAny(rightType) ||
14597+
rightType.flags & TypeFlags.Nullable ||
14598+
getSignaturesOfType(rightType, SignatureKind.Call).length ||
14599+
getSignaturesOfType(rightType, SignatureKind.Construct).length ||
14600+
isTypeSubtypeOf(rightType, globalFunctionType))) {
1459714601
error(right, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type);
1459814602
}
1459914603
return booleanType;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//// [instanceofOperatorWithInvalidStaticToString.ts]
2+
declare class StaticToString {
3+
static toString(): void;
4+
}
5+
6+
function foo(staticToString: StaticToString) {
7+
return staticToString instanceof StaticToString;
8+
}
9+
10+
declare class StaticToNumber {
11+
static toNumber(): void;
12+
}
13+
function bar(staticToNumber: StaticToNumber) {
14+
return staticToNumber instanceof StaticToNumber;
15+
}
16+
17+
declare class NormalToString {
18+
toString(): void;
19+
}
20+
function baz(normal: NormalToString) {
21+
return normal instanceof NormalToString;
22+
}
23+
24+
25+
//// [instanceofOperatorWithInvalidStaticToString.js]
26+
function foo(staticToString) {
27+
return staticToString instanceof StaticToString;
28+
}
29+
function bar(staticToNumber) {
30+
return staticToNumber instanceof StaticToNumber;
31+
}
32+
function baz(normal) {
33+
return normal instanceof NormalToString;
34+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
=== tests/cases/conformance/expressions/binaryOperators/instanceofOperator/instanceofOperatorWithInvalidStaticToString.ts ===
2+
declare class StaticToString {
3+
>StaticToString : Symbol(StaticToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 0, 0))
4+
5+
static toString(): void;
6+
>toString : Symbol(StaticToString.toString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 0, 30))
7+
}
8+
9+
function foo(staticToString: StaticToString) {
10+
>foo : Symbol(foo, Decl(instanceofOperatorWithInvalidStaticToString.ts, 2, 1))
11+
>staticToString : Symbol(staticToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 4, 13))
12+
>StaticToString : Symbol(StaticToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 0, 0))
13+
14+
return staticToString instanceof StaticToString;
15+
>staticToString : Symbol(staticToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 4, 13))
16+
>StaticToString : Symbol(StaticToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 0, 0))
17+
}
18+
19+
declare class StaticToNumber {
20+
>StaticToNumber : Symbol(StaticToNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 6, 1))
21+
22+
static toNumber(): void;
23+
>toNumber : Symbol(StaticToNumber.toNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 8, 30))
24+
}
25+
function bar(staticToNumber: StaticToNumber) {
26+
>bar : Symbol(bar, Decl(instanceofOperatorWithInvalidStaticToString.ts, 10, 1))
27+
>staticToNumber : Symbol(staticToNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 11, 13))
28+
>StaticToNumber : Symbol(StaticToNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 6, 1))
29+
30+
return staticToNumber instanceof StaticToNumber;
31+
>staticToNumber : Symbol(staticToNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 11, 13))
32+
>StaticToNumber : Symbol(StaticToNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 6, 1))
33+
}
34+
35+
declare class NormalToString {
36+
>NormalToString : Symbol(NormalToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 13, 1))
37+
38+
toString(): void;
39+
>toString : Symbol(NormalToString.toString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 15, 30))
40+
}
41+
function baz(normal: NormalToString) {
42+
>baz : Symbol(baz, Decl(instanceofOperatorWithInvalidStaticToString.ts, 17, 1))
43+
>normal : Symbol(normal, Decl(instanceofOperatorWithInvalidStaticToString.ts, 18, 13))
44+
>NormalToString : Symbol(NormalToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 13, 1))
45+
46+
return normal instanceof NormalToString;
47+
>normal : Symbol(normal, Decl(instanceofOperatorWithInvalidStaticToString.ts, 18, 13))
48+
>NormalToString : Symbol(NormalToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 13, 1))
49+
}
50+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
=== tests/cases/conformance/expressions/binaryOperators/instanceofOperator/instanceofOperatorWithInvalidStaticToString.ts ===
2+
declare class StaticToString {
3+
>StaticToString : StaticToString
4+
5+
static toString(): void;
6+
>toString : () => void
7+
}
8+
9+
function foo(staticToString: StaticToString) {
10+
>foo : (staticToString: StaticToString) => boolean
11+
>staticToString : StaticToString
12+
>StaticToString : StaticToString
13+
14+
return staticToString instanceof StaticToString;
15+
>staticToString instanceof StaticToString : boolean
16+
>staticToString : StaticToString
17+
>StaticToString : typeof StaticToString
18+
}
19+
20+
declare class StaticToNumber {
21+
>StaticToNumber : StaticToNumber
22+
23+
static toNumber(): void;
24+
>toNumber : () => void
25+
}
26+
function bar(staticToNumber: StaticToNumber) {
27+
>bar : (staticToNumber: StaticToNumber) => boolean
28+
>staticToNumber : StaticToNumber
29+
>StaticToNumber : StaticToNumber
30+
31+
return staticToNumber instanceof StaticToNumber;
32+
>staticToNumber instanceof StaticToNumber : boolean
33+
>staticToNumber : StaticToNumber
34+
>StaticToNumber : typeof StaticToNumber
35+
}
36+
37+
declare class NormalToString {
38+
>NormalToString : NormalToString
39+
40+
toString(): void;
41+
>toString : () => void
42+
}
43+
function baz(normal: NormalToString) {
44+
>baz : (normal: NormalToString) => boolean
45+
>normal : NormalToString
46+
>NormalToString : NormalToString
47+
48+
return normal instanceof NormalToString;
49+
>normal instanceof NormalToString : boolean
50+
>normal : NormalToString
51+
>NormalToString : typeof NormalToString
52+
}
53+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
declare class StaticToString {
2+
static toString(): void;
3+
}
4+
5+
function foo(staticToString: StaticToString) {
6+
return staticToString instanceof StaticToString;
7+
}
8+
9+
declare class StaticToNumber {
10+
static toNumber(): void;
11+
}
12+
function bar(staticToNumber: StaticToNumber) {
13+
return staticToNumber instanceof StaticToNumber;
14+
}
15+
16+
declare class NormalToString {
17+
toString(): void;
18+
}
19+
function baz(normal: NormalToString) {
20+
return normal instanceof NormalToString;
21+
}

0 commit comments

Comments
 (0)