Skip to content

Commit bb21cf5

Browse files
authored
Merge pull request #28920 from Microsoft/improveBindTyping
Improve 'bind' typing in --strictBindCallApply mode
2 parents b980e19 + 4d67c8f commit bb21cf5

28 files changed

+423
-221
lines changed

src/harness/fourslash.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4450,6 +4450,8 @@ namespace FourSlashInterface {
44504450
interfaceEntry("ObjectConstructor"),
44514451
constEntry("Function"),
44524452
interfaceEntry("FunctionConstructor"),
4453+
typeEntry("ThisParameterType"),
4454+
typeEntry("OmitThisParameter"),
44534455
interfaceEntry("CallableFunction"),
44544456
interfaceEntry("NewableFunction"),
44554457
interfaceEntry("IArguments"),

src/lib/es5.d.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,16 @@ interface FunctionConstructor {
295295

296296
declare const Function: FunctionConstructor;
297297

298+
/**
299+
* Extracts the type of the 'this' parameter of a function type, or 'unknown' if the function type has no 'this' parameter.
300+
*/
301+
type ThisParameterType<T> = T extends (this: unknown, ...args: any[]) => any ? unknown : T extends (this: infer U, ...args: any[]) => any ? U : unknown;
302+
303+
/**
304+
* Removes the 'this' parameter from a function type.
305+
*/
306+
type OmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends (...args: infer A) => infer R ? (...args: A) => R : T;
307+
298308
interface CallableFunction extends Function {
299309
/**
300310
* Calls the function with the specified object as the this value and the elements of specified array as the arguments.
@@ -317,7 +327,7 @@ interface CallableFunction extends Function {
317327
* @param thisArg The object to be used as the this object.
318328
* @param args Arguments to bind to the parameters of the function.
319329
*/
320-
bind<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T): (...args: A) => R;
330+
bind<T>(this: T, thisArg: ThisParameterType<T>): OmitThisParameter<T>;
321331
bind<T, A0, A extends any[], R>(this: (this: T, arg0: A0, ...args: A) => R, thisArg: T, arg0: A0): (...args: A) => R;
322332
bind<T, A0, A1, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1): (...args: A) => R;
323333
bind<T, A0, A1, A2, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2): (...args: A) => R;
@@ -347,7 +357,7 @@ interface NewableFunction extends Function {
347357
* @param thisArg The object to be used as the this object.
348358
* @param args Arguments to bind to the parameters of the function.
349359
*/
350-
bind<A extends any[], R>(this: new (...args: A) => R, thisArg: any): new (...args: A) => R;
360+
bind<T>(this: T, thisArg: any): T;
351361
bind<A0, A extends any[], R>(this: new (arg0: A0, ...args: A) => R, thisArg: any, arg0: A0): new (...args: A) => R;
352362
bind<A0, A1, A extends any[], R>(this: new (arg0: A0, arg1: A1, ...args: A) => R, thisArg: any, arg0: A0, arg1: A1): new (...args: A) => R;
353363
bind<A0, A1, A2, A extends any[], R>(this: new (arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: any, arg0: A0, arg1: A1, arg2: A2): new (...args: A) => R;

src/services/findAllReferences.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,6 +1428,10 @@ namespace ts.FindAllReferences.Core {
14281428
return [{ definition: { type: DefinitionKind.Symbol, symbol: searchSpaceNode.symbol }, references }];
14291429
}
14301430

1431+
function isParameterName(node: Node) {
1432+
return node.kind === SyntaxKind.Identifier && node.parent.kind === SyntaxKind.Parameter && (<ParameterDeclaration>node.parent).name === node;
1433+
}
1434+
14311435
function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken): SymbolAndEntries[] | undefined {
14321436
let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false);
14331437

@@ -1450,7 +1454,7 @@ namespace ts.FindAllReferences.Core {
14501454
searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
14511455
break;
14521456
case SyntaxKind.SourceFile:
1453-
if (isExternalModule(<SourceFile>searchSpaceNode)) {
1457+
if (isExternalModule(<SourceFile>searchSpaceNode) || isParameterName(thisOrSuperKeyword)) {
14541458
return undefined;
14551459
}
14561460
// falls through
@@ -1483,7 +1487,7 @@ namespace ts.FindAllReferences.Core {
14831487
// and has the appropriate static modifier from the original container.
14841488
return container.parent && searchSpaceNode.symbol === container.parent.symbol && (getModifierFlags(container) & ModifierFlags.Static) === staticFlag;
14851489
case SyntaxKind.SourceFile:
1486-
return container.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>container);
1490+
return container.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>container) && !isParameterName(node);
14871491
}
14881492
});
14891493
}).map(n => nodeEntry(n));

tests/baselines/reference/destructuringParameterDeclaration4.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(
4141
a1(...array2); // Error parameter type is (number|string)[]
4242
~~~~~~
4343
!!! error TS2552: Cannot find name 'array2'. Did you mean 'Array'?
44-
!!! related TS2728 /.ts/lib.es5.d.ts:1358:15: 'Array' is declared here.
44+
!!! related TS2728 /.ts/lib.es5.d.ts:1368:15: 'Array' is declared here.
4545
a5([1, 2, "string", false, true]); // Error, parameter type is [any, any, [[any]]]
4646
~~~~~~~~
4747
!!! error TS2322: Type 'string' is not assignable to type '[[any]]'.

tests/baselines/reference/externModule.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,20 @@ tests/cases/compiler/externModule.ts(37,3): error TS2552: Cannot find name 'XDat
6969
var d=new XDate();
7070
~~~~~
7171
!!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'?
72-
!!! related TS2728 /.ts/lib.es5.d.ts:897:15: 'Date' is declared here.
72+
!!! related TS2728 /.ts/lib.es5.d.ts:907:15: 'Date' is declared here.
7373
d.getDay();
7474
d=new XDate(1978,2);
7575
~~~~~
7676
!!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'?
77-
!!! related TS2728 /.ts/lib.es5.d.ts:897:15: 'Date' is declared here.
77+
!!! related TS2728 /.ts/lib.es5.d.ts:907:15: 'Date' is declared here.
7878
d.getXDate();
7979
var n=XDate.parse("3/2/2004");
8080
~~~~~
8181
!!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'?
82-
!!! related TS2728 /.ts/lib.es5.d.ts:897:15: 'Date' is declared here.
82+
!!! related TS2728 /.ts/lib.es5.d.ts:907:15: 'Date' is declared here.
8383
n=XDate.UTC(1964,2,1);
8484
~~~~~
8585
!!! error TS2552: Cannot find name 'XDate'. Did you mean 'Date'?
86-
!!! related TS2728 /.ts/lib.es5.d.ts:897:15: 'Date' is declared here.
86+
!!! related TS2728 /.ts/lib.es5.d.ts:907:15: 'Date' is declared here.
8787

8888

tests/baselines/reference/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.t
4141
Math.sign(1);
4242
~~~~
4343
!!! error TS2551: Property 'sign' does not exist on type 'Math'. Did you mean 'sin'?
44-
!!! related TS2728 /.ts/lib.es5.d.ts:703:5: 'sin' is declared here.
44+
!!! related TS2728 /.ts/lib.es5.d.ts:713:5: 'sin' is declared here.
4545

4646
// Using ES6 object
4747
var o = {

tests/baselines/reference/narrowExceptionVariableInCatchClause.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ tests/cases/conformance/types/any/narrowExceptionVariableInCatchClause.ts(16,17)
2424
err.massage; // ERROR: Property 'massage' does not exist on type 'Error'
2525
~~~~~~~
2626
!!! error TS2551: Property 'massage' does not exist on type 'Error'. Did you mean 'message'?
27-
!!! related TS2728 /.ts/lib.es5.d.ts:964:5: 'message' is declared here.
27+
!!! related TS2728 /.ts/lib.es5.d.ts:974:5: 'message' is declared here.
2828
}
2929

3030
else {

tests/baselines/reference/narrowFromAnyWithInstanceof.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ tests/cases/conformance/types/any/narrowFromAnyWithInstanceof.ts(22,7): error TS
2222
x.mesage;
2323
~~~~~~
2424
!!! error TS2551: Property 'mesage' does not exist on type 'Error'. Did you mean 'message'?
25-
!!! related TS2728 /.ts/lib.es5.d.ts:964:5: 'message' is declared here.
25+
!!! related TS2728 /.ts/lib.es5.d.ts:974:5: 'message' is declared here.
2626
}
2727

2828
if (x instanceof Date) {
2929
x.getDate();
3030
x.getHuors();
3131
~~~~~~~~
3232
!!! error TS2551: Property 'getHuors' does not exist on type 'Date'. Did you mean 'getHours'?
33-
!!! related TS2728 /.ts/lib.es5.d.ts:753:5: 'getHours' is declared here.
33+
!!! related TS2728 /.ts/lib.es5.d.ts:763:5: 'getHours' is declared here.
3434
}
3535

tests/baselines/reference/narrowFromAnyWithTypePredicate.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@ tests/cases/conformance/types/any/narrowFromAnyWithTypePredicate.ts(33,7): error
3939
x.mesage;
4040
~~~~~~
4141
!!! error TS2551: Property 'mesage' does not exist on type 'Error'. Did you mean 'message'?
42-
!!! related TS2728 /.ts/lib.es5.d.ts:964:5: 'message' is declared here.
42+
!!! related TS2728 /.ts/lib.es5.d.ts:974:5: 'message' is declared here.
4343
}
4444

4545
if (isDate(x)) {
4646
x.getDate();
4747
x.getHuors();
4848
~~~~~~~~
4949
!!! error TS2551: Property 'getHuors' does not exist on type 'Date'. Did you mean 'getHours'?
50-
!!! related TS2728 /.ts/lib.es5.d.ts:753:5: 'getHours' is declared here.
50+
!!! related TS2728 /.ts/lib.es5.d.ts:763:5: 'getHours' is declared here.
5151
}
5252

tests/baselines/reference/parserMemberAccessAfterPostfixExpression1.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ tests/cases/conformance/parser/ecmascript5/Expressions/parserMemberAccessAfterPo
1111
!!! error TS1005: ';' expected.
1212
~~~~~~~~
1313
!!! error TS2552: Cannot find name 'toString'. Did you mean 'String'?
14-
!!! related TS2728 /.ts/lib.es5.d.ts:517:15: 'String' is declared here.
14+
!!! related TS2728 /.ts/lib.es5.d.ts:527:15: 'String' is declared here.

0 commit comments

Comments
 (0)