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
addClickListener
method inSideBar
does 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
onClickGood
method of theHandler
class 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) = > void
is obviously not correct. But there was no error.A type mismatch is prompted only if the
SideBar
is forced to add the same type rules as theUIElement
interface.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
onClickGood
inHandler
here. He returns thenumber
type, and the editor prompt is also ofnumber
type, but can pass the test in the last sentence.
even if weaddClickListener
requires that the return value of the function isvoid
.unless you add a return type to
onClickGood
as 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
?addClickListener
ignored