Skip to content

Commit ea0d228

Browse files
authored
Fix instanceof use with Symbol.hasInstance in conjunction with union/intersection (#57602)
1 parent f4eeea0 commit ea0d228

File tree

5 files changed

+158
-7
lines changed

5 files changed

+158
-7
lines changed

src/compiler/checker.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37974,11 +37974,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3797437974
*/
3797537975
function getSymbolHasInstanceMethodOfObjectType(type: Type) {
3797637976
const hasInstancePropertyName = getPropertyNameForKnownSymbolName("hasInstance");
37977-
const hasInstanceProperty = getPropertyOfObjectType(type, hasInstancePropertyName);
37978-
if (hasInstanceProperty) {
37979-
const hasInstancePropertyType = getTypeOfSymbol(hasInstanceProperty);
37980-
if (hasInstancePropertyType && getSignaturesOfType(hasInstancePropertyType, SignatureKind.Call).length !== 0) {
37981-
return hasInstancePropertyType;
37977+
if (allTypesAssignableToKind(type, TypeFlags.NonPrimitive)) {
37978+
const hasInstanceProperty = getPropertyOfType(type, hasInstancePropertyName);
37979+
if (hasInstanceProperty) {
37980+
const hasInstancePropertyType = getTypeOfSymbol(hasInstanceProperty);
37981+
if (hasInstancePropertyType && getSignaturesOfType(hasInstancePropertyType, SignatureKind.Call).length !== 0) {
37982+
return hasInstancePropertyType;
37983+
}
3798237984
}
3798337985
}
3798437986
}

tests/baselines/reference/instanceofOperatorWithRHSHasSymbolHasInstance.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,24 @@ if (obj instanceof A) {
115115
}
116116
if (obj instanceof B) {
117117
obj; // B
118-
}
118+
}
119+
120+
// intersections
121+
// https://github.com/microsoft/TypeScript/issues/56536
122+
123+
interface HasInstanceOf { [Symbol.hasInstance](x: unknown): boolean }
124+
type Rhs14 = HasInstanceOf & object;
125+
declare const rhs14: Rhs14;
126+
lhs0 instanceof rhs14 && lhs0;
127+
128+
// unions
129+
130+
interface HasInstanceOf1 { [Symbol.hasInstance](x: unknown): x is Point }
131+
interface HasInstanceOf2 { [Symbol.hasInstance](x: unknown): x is Line }
132+
type Rhs15 = HasInstanceOf1 | HasInstanceOf2;
133+
declare const rhs15: Rhs15;
134+
lhs0 instanceof rhs15 && lhs0;
135+
119136

120137
//// [instanceofOperatorWithRHSHasSymbolHasInstance.js]
121138
lhs0 instanceof rhs0 && lhs0;
@@ -182,3 +199,5 @@ if (obj instanceof A) {
182199
if (obj instanceof B) {
183200
obj; // B
184201
}
202+
lhs0 instanceof rhs14 && lhs0;
203+
lhs0 instanceof rhs15 && lhs0;

tests/baselines/reference/instanceofOperatorWithRHSHasSymbolHasInstance.symbols

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,3 +555,64 @@ if (obj instanceof B) {
555555
obj; // B
556556
>obj : Symbol(obj, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 108, 13))
557557
}
558+
559+
// intersections
560+
// https://github.com/microsoft/TypeScript/issues/56536
561+
562+
interface HasInstanceOf { [Symbol.hasInstance](x: unknown): boolean }
563+
>HasInstanceOf : Symbol(HasInstanceOf, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 114, 1))
564+
>[Symbol.hasInstance] : Symbol(HasInstanceOf[Symbol.hasInstance], Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 119, 25))
565+
>Symbol.hasInstance : Symbol(SymbolConstructor.hasInstance, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
566+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
567+
>hasInstance : Symbol(SymbolConstructor.hasInstance, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
568+
>x : Symbol(x, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 119, 47))
569+
570+
type Rhs14 = HasInstanceOf & object;
571+
>Rhs14 : Symbol(Rhs14, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 119, 69))
572+
>HasInstanceOf : Symbol(HasInstanceOf, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 114, 1))
573+
574+
declare const rhs14: Rhs14;
575+
>rhs14 : Symbol(rhs14, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 121, 13))
576+
>Rhs14 : Symbol(Rhs14, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 119, 69))
577+
578+
lhs0 instanceof rhs14 && lhs0;
579+
>lhs0 : Symbol(lhs0, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 21, 11))
580+
>rhs14 : Symbol(rhs14, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 121, 13))
581+
>lhs0 : Symbol(lhs0, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 21, 11))
582+
583+
// unions
584+
585+
interface HasInstanceOf1 { [Symbol.hasInstance](x: unknown): x is Point }
586+
>HasInstanceOf1 : Symbol(HasInstanceOf1, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 122, 30))
587+
>[Symbol.hasInstance] : Symbol(HasInstanceOf1[Symbol.hasInstance], Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 126, 26))
588+
>Symbol.hasInstance : Symbol(SymbolConstructor.hasInstance, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
589+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
590+
>hasInstance : Symbol(SymbolConstructor.hasInstance, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
591+
>x : Symbol(x, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 126, 48))
592+
>x : Symbol(x, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 126, 48))
593+
>Point : Symbol(Point, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 0, 0))
594+
595+
interface HasInstanceOf2 { [Symbol.hasInstance](x: unknown): x is Line }
596+
>HasInstanceOf2 : Symbol(HasInstanceOf2, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 126, 73))
597+
>[Symbol.hasInstance] : Symbol(HasInstanceOf2[Symbol.hasInstance], Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 127, 26))
598+
>Symbol.hasInstance : Symbol(SymbolConstructor.hasInstance, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
599+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
600+
>hasInstance : Symbol(SymbolConstructor.hasInstance, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
601+
>x : Symbol(x, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 127, 48))
602+
>x : Symbol(x, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 127, 48))
603+
>Line : Symbol(Line, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 2, 46))
604+
605+
type Rhs15 = HasInstanceOf1 | HasInstanceOf2;
606+
>Rhs15 : Symbol(Rhs15, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 127, 72))
607+
>HasInstanceOf1 : Symbol(HasInstanceOf1, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 122, 30))
608+
>HasInstanceOf2 : Symbol(HasInstanceOf2, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 126, 73))
609+
610+
declare const rhs15: Rhs15;
611+
>rhs15 : Symbol(rhs15, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 129, 13))
612+
>Rhs15 : Symbol(Rhs15, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 127, 72))
613+
614+
lhs0 instanceof rhs15 && lhs0;
615+
>lhs0 : Symbol(lhs0, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 21, 11))
616+
>rhs15 : Symbol(rhs15, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 129, 13))
617+
>lhs0 : Symbol(lhs0, Decl(instanceofOperatorWithRHSHasSymbolHasInstance.ts, 21, 11))
618+

tests/baselines/reference/instanceofOperatorWithRHSHasSymbolHasInstance.types

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,3 +609,56 @@ if (obj instanceof B) {
609609
obj; // B
610610
>obj : B
611611
}
612+
613+
// intersections
614+
// https://github.com/microsoft/TypeScript/issues/56536
615+
616+
interface HasInstanceOf { [Symbol.hasInstance](x: unknown): boolean }
617+
>[Symbol.hasInstance] : (x: unknown) => boolean
618+
>Symbol.hasInstance : unique symbol
619+
>Symbol : SymbolConstructor
620+
>hasInstance : unique symbol
621+
>x : unknown
622+
623+
type Rhs14 = HasInstanceOf & object;
624+
>Rhs14 : HasInstanceOf & object
625+
626+
declare const rhs14: Rhs14;
627+
>rhs14 : Rhs14
628+
629+
lhs0 instanceof rhs14 && lhs0;
630+
>lhs0 instanceof rhs14 && lhs0 : any
631+
>lhs0 instanceof rhs14 : boolean
632+
>lhs0 : any
633+
>rhs14 : Rhs14
634+
>lhs0 : any
635+
636+
// unions
637+
638+
interface HasInstanceOf1 { [Symbol.hasInstance](x: unknown): x is Point }
639+
>[Symbol.hasInstance] : (x: unknown) => x is Point
640+
>Symbol.hasInstance : unique symbol
641+
>Symbol : SymbolConstructor
642+
>hasInstance : unique symbol
643+
>x : unknown
644+
645+
interface HasInstanceOf2 { [Symbol.hasInstance](x: unknown): x is Line }
646+
>[Symbol.hasInstance] : (x: unknown) => x is Line
647+
>Symbol.hasInstance : unique symbol
648+
>Symbol : SymbolConstructor
649+
>hasInstance : unique symbol
650+
>x : unknown
651+
652+
type Rhs15 = HasInstanceOf1 | HasInstanceOf2;
653+
>Rhs15 : HasInstanceOf1 | HasInstanceOf2
654+
655+
declare const rhs15: Rhs15;
656+
>rhs15 : Rhs15
657+
658+
lhs0 instanceof rhs15 && lhs0;
659+
>lhs0 instanceof rhs15 && lhs0 : Point | Line
660+
>lhs0 instanceof rhs15 : boolean
661+
>lhs0 : any
662+
>rhs15 : Rhs15
663+
>lhs0 : Point | Line
664+

tests/cases/conformance/expressions/binaryOperators/instanceofOperator/instanceofOperatorWithRHSHasSymbolHasInstance.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,20 @@ if (obj instanceof A) {
115115
}
116116
if (obj instanceof B) {
117117
obj; // B
118-
}
118+
}
119+
120+
// intersections
121+
// https://github.com/microsoft/TypeScript/issues/56536
122+
123+
interface HasInstanceOf { [Symbol.hasInstance](x: unknown): boolean }
124+
type Rhs14 = HasInstanceOf & object;
125+
declare const rhs14: Rhs14;
126+
lhs0 instanceof rhs14 && lhs0;
127+
128+
// unions
129+
130+
interface HasInstanceOf1 { [Symbol.hasInstance](x: unknown): x is Point }
131+
interface HasInstanceOf2 { [Symbol.hasInstance](x: unknown): x is Line }
132+
type Rhs15 = HasInstanceOf1 | HasInstanceOf2;
133+
declare const rhs15: Rhs15;
134+
lhs0 instanceof rhs15 && lhs0;

0 commit comments

Comments
 (0)