How can I create a function type, without providing a concrete function, that is overloaded? By inspecting the type of an overloaded function, it seems multiple call signatures on an interface/object type are the way to go:
function a(input: string): string
function a(input: number): number
function a(input: string | number): string | number {
return input
}
type A = typeof a
type B = {
(input: string): string
(input: number): number
}
const b: B = a // Okay!
Defining the same idea with a union type (without that pesky catch-all case that you need to make overloads happy) also works, the types are compatible in both directions!
type C = ((input: number) => number) & ((input: string) => string)
const c: C = b // Okay!
const a2: A = c // Okay too!
But how do I now make a function fitting this type? Do I have to necessarily also use overloading?
const x: A = (input: string | number) => input
and
const y: A = (input: string | number) => {
if (typeof input === "number") return input
if (typeof input === "string") return input
throw "excrement"
}
both fail with the exact same following error:
Type '(input: string | number) => string | number' is not assignable to type '{ (input: string): string; (input: number): number; }'.
Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
Worst of all, this happens even if I use the less readable union type C
Type '(input: string | number) => string | number' is not assignable to type 'C'.
Type '(input: string | number) => string | number' is not assignable to type '(input: number) => number'.
Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
Hopefully, I am doing something obvious wrong and there's an easy fix. Else, what are my best options when I need to demand that a function that is passed somewhere handle several call signatures with corresponding return types?