32

I've converted some classes from the conventional form:

class TestOverloads {
    private status = "blah";
    public doStuff(selector: JQuery);
    public doStuff(selector: string);
    public doStuff(selector: any) {
        alert(this.status);
    }
}

to use arrow function expressions instead:

class TestOverloads2 {
    private status = "blah";
    public doStuff = (selector: any) => {
        alert(this.status);
    }
}

so as to avoid scoping problems when the class methods are used in a callback (see here for background).

I can't work out how to recreate my overloaded function signatures though. How would I write my overloads when using the fat arrow?

1
  • 2
    Do not use fat arrow for methods. It will become a property of the class, not a prototype method. Commented Aug 17, 2015 at 8:42

2 Answers 2

47

You can write an inline type literal for the call signatures the function supports:

class TestOverloads2 {
    private status = "blah";
    public doStuff: {
        (selector: JQuery): void;
        (selector: string): void;
    } = (selector: any) => {
        alert(this.status);
    }
}

That's sort of hideous, so you might want to extract it into an interface instead:

interface SelectByJQueryOrString {
    (selector: JQuery): void;
    (selector: string): void;
}

class TestOverloads3 {
    private status = "blah";
    public doStuff: SelectByJQueryOrString = (selector: any) => {
        alert(this.status);
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

The interface type annotation is a great idea.
Note: In learning about this, I came across this TS Dos and Donts: typescriptlang.org/docs/handbook/declaration-files/… At the bottom of the page in the Use Union Types section, it mentions using unions for single-position overloads. So in this example, it would be selector: JQuery|string): void for the definition. I am wondering tho, should the actual instance also be a union instead of any? - ... = (selector: JQuery|string) => { alert...
If I try this syntax, without named interface properties, it throws an error in the implementing class saying it incorrectly implements the interface (no signature match).
As @user4275029 mentions, you should use a union. But to be clear: you should use a union INSTEAD OF an overload. So delete the overload and do public doStuff = (selector: JQuery | string) => {...}
3

It is a bit of a technicality, but you are no longer creating a function, you are creating a property (that happens to be a function).

You could solve your problem using naming rather than overloading though.

class TestOverloads2 {
    private status = "blah";
    public doStuffWithSelector = (selector: string) => {
        alert(this.status);
    }
    public doStuffWithJqueryObject = (jqo: JQuery) => {
        alert(this.status);
    }
}

If there is significant duplication, you can put that in a common function that both named functions call, for example: this.sharedStuff().

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.