Skip to content

Commit

Permalink
Merge pull request #12728 from Microsoft/instanceof-requires-callable…
Browse files Browse the repository at this point in the history
…-rhs

Instanceof requires callable or constructable right-hand side
  • Loading branch information
sandersn committed Jan 6, 2017
2 parents e9e7fce + f15a7a3 commit 5b075ff
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/compiler/checker.ts
Expand Up @@ -14586,14 +14586,18 @@ namespace ts {
}
// TypeScript 1.0 spec (April 2014): 4.15.4
// The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type,
// and the right operand to be of type Any or a subtype of the 'Function' interface type.
// and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature.
// The result is always of the Boolean primitive type.
// NOTE: do not raise error if leftType is unknown as related error was already reported
if (isTypeOfKind(leftType, TypeFlags.Primitive)) {
error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
}
// NOTE: do not raise error if right is unknown as related error was already reported
if (!(isTypeAny(rightType) || isTypeSubtypeOf(rightType, globalFunctionType))) {
if (!(isTypeAny(rightType) ||
rightType.flags & TypeFlags.Nullable ||
getSignaturesOfType(rightType, SignatureKind.Call).length ||
getSignaturesOfType(rightType, SignatureKind.Construct).length ||
isTypeSubtypeOf(rightType, globalFunctionType))) {
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);
}
return booleanType;
Expand Down
@@ -0,0 +1,34 @@
//// [instanceofOperatorWithInvalidStaticToString.ts]
declare class StaticToString {
static toString(): void;
}

function foo(staticToString: StaticToString) {
return staticToString instanceof StaticToString;
}

declare class StaticToNumber {
static toNumber(): void;
}
function bar(staticToNumber: StaticToNumber) {
return staticToNumber instanceof StaticToNumber;
}

declare class NormalToString {
toString(): void;
}
function baz(normal: NormalToString) {
return normal instanceof NormalToString;
}


//// [instanceofOperatorWithInvalidStaticToString.js]
function foo(staticToString) {
return staticToString instanceof StaticToString;
}
function bar(staticToNumber) {
return staticToNumber instanceof StaticToNumber;
}
function baz(normal) {
return normal instanceof NormalToString;
}
@@ -0,0 +1,50 @@
=== tests/cases/conformance/expressions/binaryOperators/instanceofOperator/instanceofOperatorWithInvalidStaticToString.ts ===
declare class StaticToString {
>StaticToString : Symbol(StaticToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 0, 0))

static toString(): void;
>toString : Symbol(StaticToString.toString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 0, 30))
}

function foo(staticToString: StaticToString) {
>foo : Symbol(foo, Decl(instanceofOperatorWithInvalidStaticToString.ts, 2, 1))
>staticToString : Symbol(staticToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 4, 13))
>StaticToString : Symbol(StaticToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 0, 0))

return staticToString instanceof StaticToString;
>staticToString : Symbol(staticToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 4, 13))
>StaticToString : Symbol(StaticToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 0, 0))
}

declare class StaticToNumber {
>StaticToNumber : Symbol(StaticToNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 6, 1))

static toNumber(): void;
>toNumber : Symbol(StaticToNumber.toNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 8, 30))
}
function bar(staticToNumber: StaticToNumber) {
>bar : Symbol(bar, Decl(instanceofOperatorWithInvalidStaticToString.ts, 10, 1))
>staticToNumber : Symbol(staticToNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 11, 13))
>StaticToNumber : Symbol(StaticToNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 6, 1))

return staticToNumber instanceof StaticToNumber;
>staticToNumber : Symbol(staticToNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 11, 13))
>StaticToNumber : Symbol(StaticToNumber, Decl(instanceofOperatorWithInvalidStaticToString.ts, 6, 1))
}

declare class NormalToString {
>NormalToString : Symbol(NormalToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 13, 1))

toString(): void;
>toString : Symbol(NormalToString.toString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 15, 30))
}
function baz(normal: NormalToString) {
>baz : Symbol(baz, Decl(instanceofOperatorWithInvalidStaticToString.ts, 17, 1))
>normal : Symbol(normal, Decl(instanceofOperatorWithInvalidStaticToString.ts, 18, 13))
>NormalToString : Symbol(NormalToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 13, 1))

return normal instanceof NormalToString;
>normal : Symbol(normal, Decl(instanceofOperatorWithInvalidStaticToString.ts, 18, 13))
>NormalToString : Symbol(NormalToString, Decl(instanceofOperatorWithInvalidStaticToString.ts, 13, 1))
}

@@ -0,0 +1,53 @@
=== tests/cases/conformance/expressions/binaryOperators/instanceofOperator/instanceofOperatorWithInvalidStaticToString.ts ===
declare class StaticToString {
>StaticToString : StaticToString

static toString(): void;
>toString : () => void
}

function foo(staticToString: StaticToString) {
>foo : (staticToString: StaticToString) => boolean
>staticToString : StaticToString
>StaticToString : StaticToString

return staticToString instanceof StaticToString;
>staticToString instanceof StaticToString : boolean
>staticToString : StaticToString
>StaticToString : typeof StaticToString
}

declare class StaticToNumber {
>StaticToNumber : StaticToNumber

static toNumber(): void;
>toNumber : () => void
}
function bar(staticToNumber: StaticToNumber) {
>bar : (staticToNumber: StaticToNumber) => boolean
>staticToNumber : StaticToNumber
>StaticToNumber : StaticToNumber

return staticToNumber instanceof StaticToNumber;
>staticToNumber instanceof StaticToNumber : boolean
>staticToNumber : StaticToNumber
>StaticToNumber : typeof StaticToNumber
}

declare class NormalToString {
>NormalToString : NormalToString

toString(): void;
>toString : () => void
}
function baz(normal: NormalToString) {
>baz : (normal: NormalToString) => boolean
>normal : NormalToString
>NormalToString : NormalToString

return normal instanceof NormalToString;
>normal instanceof NormalToString : boolean
>normal : NormalToString
>NormalToString : typeof NormalToString
}

@@ -0,0 +1,21 @@
declare class StaticToString {
static toString(): void;
}

function foo(staticToString: StaticToString) {
return staticToString instanceof StaticToString;
}

declare class StaticToNumber {
static toNumber(): void;
}
function bar(staticToNumber: StaticToNumber) {
return staticToNumber instanceof StaticToNumber;
}

declare class NormalToString {
toString(): void;
}
function baz(normal: NormalToString) {
return normal instanceof NormalToString;
}

0 comments on commit 5b075ff

Please sign in to comment.