-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Support custom 'Symbol.hasInstance' methods when narrowing 'instanceof' #55052
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
69f59da
[WIP] Support custom 'Symbol.hasInstance' methods when checking/narro…
rbuckton 161d1f1
Add tests for instanceof and narrowing
rbuckton 6a4f838
Accept baseline, fix lint
rbuckton af6bb55
Check derived types when using type predicates with instanceof/hasIns…
rbuckton 6a83254
Small tweaks, lint fixes, and baseline updates
rbuckton 511c955
Add go-to-definition support on 'instanceof' keyword
rbuckton 9e3adb4
Merge branch 'main' into instanceof-Symbol.hasInstance
rbuckton 4b0eafc
Fix format
rbuckton befa293
Address PR feedback
rbuckton 559047e
Comment cleanup
rbuckton 8af777e
Switch synthetic call to use use 'resolveSignature' flow
rbuckton f3e94f0
Merge branch 'main' into instanceof-Symbol.hasInstance
rbuckton 1d90af1
Run formatting
rbuckton b65f9bc
Merge branch 'main' into instanceof-Symbol.hasInstance
rbuckton 0554f56
Remove branch for 'instanceof' error message reporting
rbuckton File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
tests/baselines/reference/instanceofOperatorWithInvalidOperands.es2015.errors.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(14,11): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(15,11): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(16,11): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(17,11): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(18,11): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(19,11): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(20,11): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(21,11): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(22,11): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(34,24): error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(35,24): error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(36,24): error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(37,24): error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(38,24): error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(39,24): error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(40,24): error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(41,24): error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(42,24): error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(43,25): error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(46,11): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(46,25): error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(51,12): error TS2855: The left-hand side of an 'instanceof' expression must be assignable to the first argument of the right-hand side's '[Symbol.hasInstance]' method. | ||
| Argument of type '{ y: string; }' is not assignable to parameter of type '{ x: number; }'. | ||
| Property 'x' is missing in type '{ y: string; }' but required in type '{ x: number; }'. | ||
| instanceofOperatorWithInvalidOperands.es2015.ts(55,25): error TS2856: An object's '[Symbol.hasInstance]' method must return a boolean value for it to be used on the right-hand side of an 'instanceof' expression. | ||
|
|
||
|
|
||
| ==== instanceofOperatorWithInvalidOperands.es2015.ts (23 errors) ==== | ||
| class C { | ||
| foo() { } | ||
| } | ||
|
|
||
| var x: any; | ||
|
|
||
| // invalid left operand | ||
| // the left operand is required to be of type Any, an object type, or a type parameter type | ||
| var a1: number; | ||
| var a2: boolean; | ||
| var a3: string; | ||
| var a4: void; | ||
|
|
||
| var ra1 = a1 instanceof x; | ||
| ~~ | ||
| !!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| var ra2 = a2 instanceof x; | ||
| ~~ | ||
| !!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| var ra3 = a3 instanceof x; | ||
| ~~ | ||
| !!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| var ra4 = a4 instanceof x; | ||
| ~~ | ||
| !!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| var ra5 = 0 instanceof x; | ||
| ~ | ||
| !!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| var ra6 = true instanceof x; | ||
| ~~~~ | ||
| !!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| var ra7 = '' instanceof x; | ||
| ~~ | ||
| !!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| var ra8 = null instanceof x; | ||
| ~~~~ | ||
| !!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| var ra9 = undefined instanceof x; | ||
| ~~~~~~~~~ | ||
| !!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
|
|
||
| // invalid right operand | ||
| // the right operand to be of type Any or a subtype of the 'Function' interface type | ||
| var b1: number; | ||
| var b2: boolean; | ||
| var b3: string; | ||
| var b4: void; | ||
| var o1: {}; | ||
| var o2: Object; | ||
| var o3: C; | ||
|
|
||
| var rb1 = x instanceof b1; | ||
| ~~ | ||
| !!! error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| var rb2 = x instanceof b2; | ||
| ~~ | ||
| !!! error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| var rb3 = x instanceof b3; | ||
| ~~ | ||
| !!! error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| var rb4 = x instanceof b4; | ||
| ~~ | ||
| !!! error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| var rb5 = x instanceof 0; | ||
| ~ | ||
| !!! error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| var rb6 = x instanceof true; | ||
| ~~~~ | ||
| !!! error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| var rb7 = x instanceof ''; | ||
| ~~ | ||
| !!! error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| var rb8 = x instanceof o1; | ||
| ~~ | ||
| !!! error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| var rb9 = x instanceof o2; | ||
| ~~ | ||
| !!! error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
| var rb10 = x instanceof o3; | ||
| ~~ | ||
| !!! error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
|
|
||
| // both operands are invalid | ||
| var rc1 = '' instanceof {}; | ||
| ~~ | ||
| !!! error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter. | ||
| ~~ | ||
| !!! error TS2857: The right-hand side of an 'instanceof' expression must be either of type 'any', an object type with a '[Symbol.hasInstance]()' method, or a type assignable to the 'Function' interface type. | ||
|
|
||
| // @@hasInstance restricts LHS | ||
| var o4: {[Symbol.hasInstance](value: { x: number }): boolean;}; | ||
| var o5: { y: string }; | ||
| var ra10 = o5 instanceof o4; | ||
| ~~ | ||
| !!! error TS2855: The left-hand side of an 'instanceof' expression must be assignable to the first argument of the right-hand side's '[Symbol.hasInstance]' method. | ||
| !!! error TS2855: Argument of type '{ y: string; }' is not assignable to parameter of type '{ x: number; }'. | ||
| !!! error TS2855: Property 'x' is missing in type '{ y: string; }' but required in type '{ x: number; }'. | ||
| !!! related TS2728 instanceofOperatorWithInvalidOperands.es2015.ts:49:40: 'x' is declared here. | ||
|
|
||
| // invalid @@hasInstance method return type on RHS | ||
| var o6: {[Symbol.hasInstance](value: unknown): number;}; | ||
| var rb11 = x instanceof o6; | ||
| ~~ | ||
| !!! error TS2856: An object's '[Symbol.hasInstance]' method must return a boolean value for it to be used on the right-hand side of an 'instanceof' expression. |
107 changes: 107 additions & 0 deletions
107
tests/baselines/reference/instanceofOperatorWithInvalidOperands.es2015.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| //// [tests/cases/conformance/expressions/binaryOperators/instanceofOperator/instanceofOperatorWithInvalidOperands.es2015.ts] //// | ||
|
|
||
| //// [instanceofOperatorWithInvalidOperands.es2015.ts] | ||
| class C { | ||
| foo() { } | ||
| } | ||
|
|
||
| var x: any; | ||
|
|
||
| // invalid left operand | ||
| // the left operand is required to be of type Any, an object type, or a type parameter type | ||
| var a1: number; | ||
| var a2: boolean; | ||
| var a3: string; | ||
| var a4: void; | ||
|
|
||
| var ra1 = a1 instanceof x; | ||
| var ra2 = a2 instanceof x; | ||
| var ra3 = a3 instanceof x; | ||
| var ra4 = a4 instanceof x; | ||
| var ra5 = 0 instanceof x; | ||
| var ra6 = true instanceof x; | ||
| var ra7 = '' instanceof x; | ||
| var ra8 = null instanceof x; | ||
| var ra9 = undefined instanceof x; | ||
|
|
||
| // invalid right operand | ||
| // the right operand to be of type Any or a subtype of the 'Function' interface type | ||
| var b1: number; | ||
| var b2: boolean; | ||
| var b3: string; | ||
| var b4: void; | ||
| var o1: {}; | ||
| var o2: Object; | ||
| var o3: C; | ||
|
|
||
| var rb1 = x instanceof b1; | ||
| var rb2 = x instanceof b2; | ||
| var rb3 = x instanceof b3; | ||
| var rb4 = x instanceof b4; | ||
| var rb5 = x instanceof 0; | ||
| var rb6 = x instanceof true; | ||
| var rb7 = x instanceof ''; | ||
| var rb8 = x instanceof o1; | ||
| var rb9 = x instanceof o2; | ||
| var rb10 = x instanceof o3; | ||
|
|
||
| // both operands are invalid | ||
| var rc1 = '' instanceof {}; | ||
|
|
||
| // @@hasInstance restricts LHS | ||
| var o4: {[Symbol.hasInstance](value: { x: number }): boolean;}; | ||
| var o5: { y: string }; | ||
| var ra10 = o5 instanceof o4; | ||
|
|
||
| // invalid @@hasInstance method return type on RHS | ||
| var o6: {[Symbol.hasInstance](value: unknown): number;}; | ||
| var rb11 = x instanceof o6; | ||
|
|
||
| //// [instanceofOperatorWithInvalidOperands.es2015.js] | ||
| class C { | ||
| foo() { } | ||
| } | ||
| var x; | ||
| // invalid left operand | ||
| // the left operand is required to be of type Any, an object type, or a type parameter type | ||
| var a1; | ||
| var a2; | ||
| var a3; | ||
| var a4; | ||
| var ra1 = a1 instanceof x; | ||
| var ra2 = a2 instanceof x; | ||
| var ra3 = a3 instanceof x; | ||
| var ra4 = a4 instanceof x; | ||
| var ra5 = 0 instanceof x; | ||
| var ra6 = true instanceof x; | ||
| var ra7 = '' instanceof x; | ||
| var ra8 = null instanceof x; | ||
| var ra9 = undefined instanceof x; | ||
| // invalid right operand | ||
| // the right operand to be of type Any or a subtype of the 'Function' interface type | ||
| var b1; | ||
| var b2; | ||
| var b3; | ||
| var b4; | ||
| var o1; | ||
| var o2; | ||
| var o3; | ||
| var rb1 = x instanceof b1; | ||
| var rb2 = x instanceof b2; | ||
| var rb3 = x instanceof b3; | ||
| var rb4 = x instanceof b4; | ||
| var rb5 = x instanceof 0; | ||
| var rb6 = x instanceof true; | ||
| var rb7 = x instanceof ''; | ||
| var rb8 = x instanceof o1; | ||
| var rb9 = x instanceof o2; | ||
| var rb10 = x instanceof o3; | ||
| // both operands are invalid | ||
| var rc1 = '' instanceof {}; | ||
| // @@hasInstance restricts LHS | ||
| var o4; | ||
| var o5; | ||
| var ra10 = o5 instanceof o4; | ||
| // invalid @@hasInstance method return type on RHS | ||
| var o6; | ||
| var rb11 = x instanceof o6; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.