Add a type to support wrappers

Topics: General
Oct 26, 2012 at 7:45 AM

Due to the dynamic nature of JS, it is common practice to wrap a function in order to add some functionality. A simple example would be the standard "bind" function.

However in TypeScript you cannot express this in a declaration file. It would be nice to have a special type (lets say CallerType) that would inform the compiler (and of course intellisense) of this construct. For example:

interface Function { 
   bind(thisArg: any, ...argArray: any[]): CallerType;

Now the compiler knows that we don't talk about just any Function that is returned, but about a function that has the same signature as the function on which bind is invoked.

-- Peter

Oct 26, 2012 at 3:50 PM

There's been a lot of discussion around 'generics', which would help you describe situations like this (among others).  We're definitely looking into that area.

Oct 26, 2012 at 5:23 PM

I'm aware of generics coming to TS in the future, but was not sure that would help in the above situation. So it would be possible to declare something like this:

interface Function<A> { 
   bind(thisArg: any, ...argArray: any[]): A;

And automatically any function would match the above interface definition? 
That would be great.



Oct 29, 2012 at 5:41 PM

Ahh, I think I see the part of your question I missed earlier. 

In addition to generics, it looks like you're asking about 'thisType' or 'selfType', where an object that implements an interface could have the interface reference the implementing type.  Something like this:

interface Serializable {
    deserialize(s:string): selfType;

class Foo implements Serializable {
    deserialize(s:string): Foo { return this; }

Does this sound like what you're suggesting? 

If so, this particular approach doesn't quite have the utility users would need.  While we could check to make sure that the class indeed does have a method that returns the class itself as the type, this isn't quite enough.  What I think you're suggesting, is to have the interface itself become more expressive, so that if you say:

function f (s: Serializable) {
    // Now we know s.deserialize returns specific type

Unfortunately, we can't know that.  While we can check the interface is implemented, we can't also carry along the info about what type implemented the interface (this is actually intentional so that we can separately type-check separate sections of code).  To get this, you'd have to pass in the type with Serializable, like you mention:

interface Serializable<T> {
    deserialize(s:string): T;

function f (s: Serializable<Foo>) : Foo {
    return s.deserialize("foo");


Oct 29, 2012 at 11:19 PM

Thanks for the extensive reply. What you called selfType (and I called CallerType) is indeed what I was looking for. But the way I envisioned it to work is slightly different from your examples (i believe).

Perhaps a simple example can demonstrate more clearly what I was looking for (my previous example used a function,which is perhaps not the clearest example, so this time a Node).

Normally the following code snippet would cause the compiler to throw an error:


var elem:Element = ....;

Because cloneNode is declared to return a Node and of course a Node doesn't have the attribute tagName. If we now introduce the SelfType:

interface Node { 
   cloneNode(deep?:bool): selfType

The same code would now compile just fine:

var elem:Element = ....;

The compiler knows that the caller of the method cloneNode (elem) is of the type Element. So then it also knows that the return type of cloneNode is of the type Element (that is what SelfType indicates). And tagName is a known attribute of the Element type, so the compiler is happy again.

However after your examples I realized you could do the same with generics:


interface Node<T> {
   cloneNode(deep?: bool): T;

interface Element extends Node<Element> {

Is this what would be possible with generics, even for declarations for things like DOM API ?


P.S Even without this features, I think the TypeScript team doing a great job capturing the dynamic nature of JS in a type system. 

Oct 30, 2012 at 8:29 PM

Right, with generics you have a way of passing in a type that captures what the expected return of cloneNode is.  It's arguably a little more verbose, but it does address that issue.