Reputation:
I have this method signature on a class:
lock(key: string, opts: any, cb?: LMClientLockCallBack): void;
if a user uses it like so:
lock('foo', null, (err,val) => {
});
they will get the right typings. However, if they omit the options argument and do this:
lock('foo', (err,val) => {
});
then tsc
sees the callback function as type any
, just like this:
Is there any way to allow users to avoid passing an empty object or null as the second argument, and shift the callback over?
I tried overloading the method, into two definitions:
lock(key: string, cb: LMClientLockCallBack, n?: LMClientLockCallBack) : void;
lock(key: string, opts: any, cb?: LMClientLockCallBack) { ... }
but it still doesn't compile, there are new problems:
and if I try this:
lock(key: string, cb: LMClientLockCallBack) : void;
lock(key: string, opts: any, cb?: LMClientLockCallBack) { ... }
I get this:
Surely there must be a solution to this one?
Upvotes: 8
Views: 5522
Reputation: 10227
When overloading the method in TypeScript, the implementation doesn't count as one of overloads. You should thus create three function definitions: two ones for different overloads, as you've already done, and the third - with optional argument and real implementation, which is in your code erroneously connected to the second overload definition. So you'll have:
lock(key: string, cb: LMClientLockCallBack) : void;
lock(key: string, opts: any, cb: LMClientLockCallBack): void;
lock(key: string, opts: any, cb?: LMClientLockCallBack) { ... }
So, if the second argument is a callback - user will get the first overload typings, if it is anything else, but the third argument is a callback - the second overload typings. But in both cases they will call the same implementation, just like it would be in pure JavaScript.
Upvotes: 19