(Using A and B to refer to the signatures separately)
TypeScript is actually correct here because T extends fn does not mean that T can only be "A" or "B". T extends fn is a constraint that means T must be assignable to fn. Sure, "A" and "B" are assignable to fn, but the type A | B is also assignable to fn.
That means someone could call your function like this:
combine<fn>(fns.A, 0);
If TypeScript were to allow this, then this call would be valid! This would result in unexpected and undesirable behavior. But don't fret, I've got two possible workarounds, each with their pros and cons.
One is to use an external signature and write the internal signature like this:
function combine<T extends fn>(fn: T, param: Parameters<T>[0]): ReturnType<T>;
function combine<T extends (x: unknown) => R, R>(fn: T, param: Parameters<T>[0]): R {
return fn(param);
}
It's a bit ugly and unsafe but it does work while retaining the original signature. However, like I mentioned above, people can call it with the type fn instead of "A" or "B".
Playground
Similar to the first, this one uses individual overloads instead. It's slightly better than the first because it prevents users from calling it with unions of functions, but it's a lot more to type.
function combine(fn: typeof fns.A, param: string): string;
function combine(fn: typeof fns.B, param: number): number;
function combine<T extends (x: unknown) => R, R>(fn: T, param: Parameters<T>[0]): R {
return fn(param)
}
Playground
There's probably better solutions, but I haven't had my morning coffee yet. Hopefully you at least understand why it's an error, but I'll still edit the answer with better solutions when I think of them.