Specifying the type of `this`?

Topics: General
Oct 12, 2012 at 12:18 AM
Edited Oct 12, 2012 at 12:20 AM

The `this` is sometimes supplied to a callback function and is expected to be of a certain type.

For example, the functions passed to the JQueryUI Widget factory will be provided a `this` which meets an interface, say JQueryUIWidget.

How can we model the `_create()` function of the custom Widget prototype so that the implicit `this` parameter is known to the type inferencer to implement JQueryUIWidget?


Oct 12, 2012 at 1:36 AM
Edited Oct 12, 2012 at 1:38 AM

I just kind of mocked this up to run in the playground and I've never tried to implement a JQueryUI Widget so this may or may not help.  It does show how you can get a strongly typed 'this' pointer for something that isn't a class.

Scanning the docs for creating a widget it looks like they want you to call $.widget() with the name of your widget and the widgets definition.  So I extended JQuery to support the $.widget() method and then implemented a base JQueryUIWidget interface (not complete) defining the members common to all widgets.  This is essentially a base class and it looks like your widget is free to add any other members it wants so I modeled that by defining a DemoWidget interface that extends JQueryUIWidget.  In the call to $.widget() I then cast the JSON object passed in to be an instance of DemoWidget which works because it extends JQueryUIWidget.  Within each function definition you now have a strongly typed 'this' pointer which is what you want. 

declare var jQuery: JQuery;

(function( $: JQuery ) {  
	$.widget( "demo.multi", <DemoWidget>{
     	// These options will be used as defaults    
		options: { 
      		clear: null
     	// Set up the widget
    	_create: function() {    
			this.foo = 'test';
    	// Use the _setOption method to respond to changes to options    
		_setOption: function( key, value ) {      
			switch( key ) {
        		case "clear":
          		// handle changes to clear option          
      		// In jQuery UI 1.8, you have to manually invoke the _setOption method from the base widget      
	  		$.Widget.prototype._setOption.apply( this, arguments );
      		// In jQuery UI 1.9 and above, you use the _super method instead
			this._super( "_setOption", key, value );    
    	// Use the destroy method to clean up any modifications your widget has made to the DOM    
		destroy: function() {
			// In jQuery UI 1.8, you must invoke the destroy method from the base widget      
			$.Widget.prototype.destroy.call( this );
			// In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method    
}( jQuery ) );

interface JQuery {
	widget(name:string, widget: JQueryUIWidget);
	Widget: any;

interface JQueryUIWidget {
	_create: () => any;
	_setOption?: (key: string, value) => any;
	destroy?: () => void;

interface DemoWidget extends JQueryUIWidget {
	foo: string;
Oct 12, 2012 at 1:45 PM

Thanks for alerting me to type assertions.  I don't like this approach very much, though.  The object literal is a widget prototype - it isn't a Widget itself, and it doesn't inherit.  It's just a bag of static methods which will be .call(widget, ...) or .apply(widget, [...]) by the consuming $.widget() code.  We have to put question marks on every member, since they're all optional for the prototype to supply even though the supplied `this` will actually have those things.

I'm thinking that a syntax like the following would work to optionally supply the type information to the otherwise implicit `this` parameter.  An optional first parameter called "this", which is I think illegal in javascript and so would not pose any conflict, should be allowed:


$.widget( "demo.multi", {
    _setOption: function( this : JQueryUIWidget, key: string, value) { 


When calling this function, the type inferencer and intellisense would know not to expect a value for that first parameter in the arguments list.  But it could help enforce that the function is .call()ed or .apply()ed correctly.

It would be useful in lots of scenarios, but I'm having trouble coming up with a more general example.  In many very general situations, the cheat of section 4.9.2 Arrow Function Expressions works because outer scope knows supplies a closure (unlike the case of the widget), or as in the callback for Array.forEach, `this` is already correctly the target array.

Oct 28, 2012 at 4:14 PM

I use a kind of hack, but it seems to work : 

var that : JQuery = <JQuery><Object>this;

<JQuery>this alone does not work, you get an error that this can not be cast to JQuery.