Shachar Har-Shuv
Shachar Har-Shuv

Reputation: 822

TypeScript: Carrying a method with overloading signatures without losing the overload

The example is with strict null checking. Consider I have the following function declaration:

declare function f(value: null, multiplier: number): null;
declare function f(value: string, multiplier: number): number;
declare function f(value: string | null, multiplier: number): number | null;

Now I want to carry it like this:

const f2 = (value) => f(value, 2);

Seems like the inferred parameter type is "any" and the inferred return type is "number | null".

Is there a way to make typescript infer the new function type correctly so it preserves overloads, without having to redefine all signatures?

The expected call signature results should be identical to this:

function f2(value: null): null;
function f2(value: string): number;

Upvotes: 1

Views: 62

Answers (1)

Zack Mitkin
Zack Mitkin

Reputation: 356

There's no way in typescript to partially fill a functions call signature from another function. Like it won't assume what value param.

Here's an example for clarification:

function someOtherFunction(x: number) {}
function test(x) {
   // we can't assume `x` is number just because it's used as one for input to the other function.
   someOtherFunction(x, 5);
}

I'd refactor it to be something like this instead:

type ValueType = null | string;
declare function f(value: ValueType, multiplier: number): number | null;

const f2 = (value: ValueType) => f(value, 2);

The closest thing I can come up with is something like this:

declare function f<T = string | null>(
  value: T,
  multiplier: number
): T extends string ? number : null;

const f2 = (value: string | null) => f<typeof value>(value, 5);

const x = f2(null); // x: number | null
const x2 = f2("5"); // x2: number | null

But I think this pretty much just does the function overloading automatically using conditional types...

Upvotes: 1

Related Questions