For those interested in ensuring the compiler identifies bound methods with incorrect parameter counts without focusing on the this
context, consider enabling the --strictBindCallApply compiler option:
class StringListeningClassThing {
myString = "hey";
oneParam(x: string) {
return x + this.myString;
}
twoParams(x: number, y: string) {
return x.toFixed(2) + y + this.myString;
}
}
const onPageSizeSelected = new EventTyped<string>();
const stringListenerThingy = new StringListeningClassThing();
onPageSizeSelected.Attach(
stringListenerThingy.twoParams); // error
onPageSizeSelected.Attach(
stringListenerThingy.twoParams.bind(stringListenerThingy)); // error
onPageSizeSelected.Attach(
stringListenerThingy.oneParam.bind(stringListenerThingy)); // okay
onPageSizeSelected.Attach(
stringListenerThingy.twoParams.bind(stringListenerThingy, 2)); // okay
The above steps may serve your needs. However, there are still some type safety concerns at play:
Regrettably, TypeScript does not naturally excel at type-checking this
contexts:
onPageSizeSelected.Attach(
stringListenerThingy.oneParam); // no error
onPageSizeSelected.Attach(
stringListenerThingy.oneParam.bind({ notGood: true })); // no error
Accepting these scenarios could lead to runtime errors as stringListenerThingy
's methods may dereference an incorrect this
.
There is an ongoing discussion at microsoft/TypeScript#7968 regarding the addition of a --strictThis
compiler option to prevent the propagation of mis-bound functions. While this proposal has not been implemented yet, it has been acknowledged that adoption could have significant impacts due to potential breaks in existing code and compiler performance. Users who advocate for this feature should engage on the issue and share their perspectives.
If enforcing this check is imperative, users have the option to manually introduce this
parameters throughout their codebase, as demonstrated below:
// Explicitly define void this-context for Listener interface
export interface Listener<T> {
(this: void, event: T): any;
}
// Explicitly assign class-based this-context to all methods
class StringListeningClassThing {
myString = "hey";
oneParam(this: StringListeningClassThing, x: string) {
return x + this.myString;
}
twoParams(this: StringListeningClassThing, x: number, y: string) {
return x.toFixed(2) + y + this.myString;
}
}
Following these adjustments, errors highlighted in the previous examples will now be flagged:
// Achieve type safety
onPageSizeSelected.Attach(
stringListenerThingy.oneParam); // error
onPageSizeSelected.Attach(
stringListenerThingy.oneParam.bind({ notGood: true })); // error
Therefore, while the compiler can indeed enforce these rules, it currently requires manual intervention until the potential implementation of --strictThis
.
Explore the code on TypeScript Playground