I am a beginner of TypeScript, and I have doubts in the section < this parameters in callback function > in the "functions" chapter of the official manual guide of TypeScript.
there is nothing wrong with the logic and running results of the instance provided by the official documentation, but I did a few additional tests myself, which caused some unexpected problems.
Development environment:
VSCode 1.26.1 TypeScript 3.0.1
this example is used to provide this correct type judgment
define a callback interface:
interface UIElement {
addClickListener(onclick: (this: void, e: Event) => void): void;
}
defines a callback class that provides a method as a callback function:
class Handler {
info: string;
onClickGood(this: void, e: Event) {
// can"t use this here because it"s of type void!
console.log("clicked!");
}
}
let h = new Handler();
uiElement.addClickListener(h.onClickGood);// uiElement,
because I lack a class that implements the interface, I define a class myself and implement the UIElement interface, which is also the cause of the problem.
my complete example:
interface UIElement {
addClickListener(onclick: (this: void, e: string) => void): void;
}
class SideBar implements UIElement {
addClickListener(onclick: (this: void, e: string) => void): void {
onclick("event");
}
}
class Handler {
info: string = "ok";
onClickGood(this:void,event:string):void{
console.log("clicked");
console.log(event);
}
}
let h: Handler = new Handler();
let uiElement: SideBar = new SideBar();
uiElement.addClickListener(h.onClickGood)
this example can be run without errors. I have provided a SideBar class. The only change is that the type of Event in the callback function has been changed to String .
example link:
the location of the https://www.tslang.cn/docs/ha.< H2 > question < / H2 >
example at the bottom of the page
-
A class implements the method defined by the interface to obtain the callback function, and the method implemented by the class may not verify its internal parameter structure (specific type of callback)
interface UIElement { addClickListener(onclick: (this: void, e: string) => void): void; } class SideBar implements UIElement { addClickListener(onclick){ onclick("event"); } }there is no problem with writing this way. Even if the
addClickListenermethod inSideBardoes not provide complete type verification, TypeScript will automatically infer it. The evidence is as followsclass SideBar implements UIElement { addClickListener(onclick,hello){ onclick("event"); } }I added an extra parameter to this method. Since there is no definition in
.UIElement, an error is prompted here, which proves that TypeScript"s type inference works properly, which is in line with our expectations, but then it doesn"t work properlyinterface UIElement { addClickListener(onclick: (this: void, e: string) => void): void; } class SideBar implements UIElement { addClickListener(onclick){ onclick("event"); } } class Handler { info: string; onClickGood(this:Handler,event:string):void{ console.log("clicked!"); console.log(event); } } let h:Handler = new Handler(); let uiElement:SideBar = new SideBar(); uiElement.addClickListener(h.onClickGood)//in the last sentence of this example, we pass the
onClickGoodmethod of theHandlerclass to theaddClickListener
ofSideBar. Note that if the previous structure matches the normal operation effect, the acceptance type of the callback function here should beonclick: (this: void, e: string) = > void
, but the type we passed in the past is(this:Handler,event:string) = > voidis obviously not correct. But there was no error.A type mismatch is prompted only if the
SideBaris forced to add the same type rules as theUIElementinterface.class SideBar implements UIElement { addClickListener(onclick: (this: void, e: string) => void):void{ onclick("event"); } }class Handler { info: string; onClickGood(this:Handler,event:string):void{ // can"t use this here because it"s of type void! console.log("clicked!"); console.log(event); } } let h:Handler = new Handler(); let uiElement:SideBar = new SideBar(); uiElement.addClickListener(h.onClickGood)// -
the return value of the callback function defined by the interface can actually be inconsistent with the type defined by the interface
continue to use the previous example:interface UIElement { addClickListener(onclick: (this: void, e: string) => void): void; } class SideBar implements UIElement { addClickListener(onclick: (this: void, e: string) => void) :void{ onclick("event"); } }class Handler { info: string; onClickGood(this:void,event:string){ console.log("clicked!"); console.log(event); return 123; } } let h:Handler = new Handler(); let uiElement:SideBar = new SideBar(); uiElement.addClickListener(h.onClickGood)//notice the
onClickGoodinHandlerhere. He returns thenumbertype, and the editor prompt is also ofnumbertype, but can pass the test in the last sentence.
even if weaddClickListenerrequires that the return value of the function isvoid.unless you add a return type to
onClickGoodas well:class Handler { info: string; onClickGood(this:void,event:string):void{ // can"t use this here because it"s of type void! console.log("clicked!"); console.log(event); return 123; } }now the value of return is finally judged to be incorrect, but isn"t the callback function type rule made in
?addClickListenerignored
