I've this type definition, incomplete at the moment:
export type Type1 = string;
export type Type2 = string | { [index: string]: any } | Array<string | undefined | boolean>;
export type Type3 = { [index: string]: any } | Array<string | undefined | boolean>;
export type Type4 = (arg1?: Type2 | Type3, arg2?: Type3) => string | undefined;
export default function myLibrary(arg1?: Type1, arg2?: Type2, arg3?: Type3): Type4;
Normally the library is used in scenarios like the one of the following example, types declaration works properly in this example, within React application:
const myCustomLibrary = myLibrary('string')
...
<span className={myCustomLibrary({
key: value
})}/>
where value
can be anything like a boolean, string, object..
But I said incomplete definition because it is not covering the following scenario, still within a React application:
<span className={myLibrary('string', {
key: value
})}/>
Basically myLibrary
can return a function or also a string, depending of the values received as input according to a specific internal logic. So the type Type4
could also be a string, not only a method returning a string. Current type declaration offers just the type Type4
as output, it misses a simple string. In fact while returning a string, here is the error:
TS2322: Type 'Type4' is not assignable to type 'string'.
So I thought to add a string to the return value of myLibrary
export default function myLibrary(arg1?: Type1, arg2?: Type2, arg3?: Type3): Type4 | string;
but this ruins other scenarios currently working (the one receiving the actual Type4
and it gives this error
Cannot invoke an expression whose type lacks a call signature. Type 'string | Type4' has no compatible call signatures.ts(2349)
Feel in a loophole, what am I doing wrong?
I could solve everything defining Type4
as any
, but that is not what I want to achieve.
The solution is indeed the usage of Overloads concept, thanks @AlekseyL. for the tip in the comments, for clearer reference I add here the proper code fix.