0

I know that function overloading is not supported in typescript and javascript.

And I'm studying a detour method to work like this function overloading.

My case is as follows.

first:

The last ans first argument is fixed.

public A(arg1:number, arg2:number, argLast:any){

}

public A(arg1:number, arg2:number, arg3:Array<any>, argLast:any){

}

Second :

enter image description here

There is an indicator for whether the function is overloaded.

Of course, as in the above example, it is possible, but I have to create it through a new interface, so it does not fit in my case.

I have tried various function overloading methods.

I also implemented it through john resig blog.

(https://johnresig.com/blog/javascript-method-overloading/)

The code below is an example I made through the above blog.

function addMethod (object, name, fn) {
  var old = object[ name ]
  object[ name ] = function () {
    if (fn.length === arguments.length) {
      return fn.apply(this, arguments)
    } else if (typeof old === 'function') {
      return old.apply(this, arguments)
    }
  }
}

export class Users{
  find(...arg: any[]){
    Users.prototype['findOVF'](arg)
  }
}
addMethod(Users.prototype, 'findOVF', function () {
  console.log('ARG 0')
})
addMethod(Users.prototype, 'findOVF', function (name:string, age:number) {
  console.log('ARG 2')
})
addMethod(Users.prototype, 'findOVF', function (first_name:string, last_name:string,age:number) {
  console.log('ARG 3')
})

var users = new Users()
users.find() 
users.find('John',19) 
users.find('John', 'Resig', 19) 

When I use this method, I call the function with the parameter (... arg).

I've tried to implement all the methods of the blog below.

(https://blog.mariusschulz.com/2016/08/18/function-overloads-in-typescript)

public A(arg1:number, arg2:number, argLast:any){

}

public A(arg1:number, arg2:number, arg3:Array<any>|null, argLast:any){

}

If I implement function overloading this way, I get an error every time I call the A function. It's not really function overloading.

But I have not found a way to implement these two elements at the same time.

I want to know if this is impossible with the typescript grammar or if there is any other possibility.

Thanks for seeing my awkward English.

3
  • It's not really clear to me what does not work. COuld you post a complete example with the code you would like to work but does not work or does not work as expected ? Commented Aug 17, 2018 at 10:42
  • ok. i`ll post right now. However, the writing will be very long. I hope you understand. Commented Aug 17, 2018 at 10:43
  • I tried to describe the method I tried. I have a question too ... I'm sorry. Commented Aug 17, 2018 at 10:51

1 Answer 1

2

You can create overloads in typescript but all the overloads have a single implementation and it's up to you to differentiate between them. The simplest solution, if your methods are all differentiated just by number of parameters is this:

class User { }
export class Users {
    find(): User;
    find(name: string, age: number): User;
    find(first_name: string, last_name: string, age: number): User
    find(...args: [any?, any?, any?]): User {
        if (args.length == 0) {
            return null as any;
        } else if (args.length == 1) {
            let [name, age, _]: [string?, number?, any?] = args;
            console.log(`${name}, ${age}`);
            return null as any;
        } else if (args.length == 2){
            let [first_name, last_name, age]: [string?, string?, number?] = args;
            console.log(`${first_name}, ${last_name}, ${age}`);
            return null as any;
        } else {
            throw "Not implemented";
        }
    }
}

Playground link

The above solution preserves call site type safety, your solution does not since the argument to find is any[] in your example.

You could use a more automated approach by defining a function that will create an overloaded function form an array of functions but wather this extra complexity is worth it you be the judge.

type UnionToIntersection<U> =
    (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never

function overloads<TThis>(){
    return function<T extends Array<(this: TThis, ...args: any[]) => any>>(...fns: T): UnionToIntersection<T[number]> {
        return function (this: TThis, ...args: any[]) {
            for (var fn of fns) {
                if (fn.length === args.length) {
                    return fn.apply(this, args);
                }
            }
            throw "Not implemented";
        } as any
    }
}

class User { }
export class Users {
    member: string = "M"
    find = overloads<Users>()(
        function () {
            console.log('ARG 0');
            this.member // this is Users 
        },
        function (name: string, age: number) {
            console.log('ARG 2')
        },
        function (first_name: string, last_name: string, age: number) {
            console.log('ARG 3')
        }
    );
}

var users = new Users()
users.find('John', 19)
users.find('John', 'Resig', 19) 

Playground link

Or a version that assigns the function to the prototype not the instance:

export class Users {
    member: string = "M"
}

let find = overloads<Users>()(
    function () {
        console.log('ARG 0');
        this.member // this is Users 
    },
    function (name: string, age: number) {
        console.log('ARG 2')
    },
    function (first_name: string, last_name: string, age: number) {
        console.log('ARG 3')
    }
);
export interface Users {
    find: typeof find;
}
Users.prototype.find = find;

Playground link

Sign up to request clarification or add additional context in comments.

9 Comments

thank you your kindly answer!. but i have some error : rest parameter must be of an array type. and JSDoc types can only be used inside documentation comments.
@naiad what version of typescript are you using, the above code works for 3.0
@naiad the first version will work for any version of typescript, and is the simplest one to understand, I would go with that one for simple overloads
my IDE is visual studio code and when i write "tsc -v" command : Version 3.0.1
@naiad added playground links to all examples, they all work without error and should work in your IDE as well.
|

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.