So I have a problem getting specific Parameters from a function which is overloaded. For example:
// someLib.d.ts
type Component<T> = {};
type A = {};
type B = {};
type C = {};
type Opts = {};
type ModernOpts = {};
export declare function mount(component: A, options: Opts): Component<A>;
export declare function mount(component: B, options: Opts): Component<B>;
export declare function mount(component: C, options: ModernOpts): Component<C>;
The problem is, somehow if I do this on another file:
import { mount } from 'someLib';
type specificMountParams = Parameters<typeof mount>;
The param I get is [C, ModernOpts]
, and it seems like there's no way to get the parameter of [A, Opts]
, or [B, Opts]
.
Is there any way to retrieve specific parameter from overloaded functions? (So I can get [A, Opts]
parameter)
Those types (A, B, Opts)
are not exported by the library, and I need to create a function that needs such type to do something similar.
From the docs:
When inferring from a type with multiple call signatures (such as the type of an overloaded function), inferences are made from the last signature (which, presumably, is the most permissive catch-all case). It is not possible to perform overload resolution based on a list of argument types.
COnsider this example:
function foo(a: number): number
function foo(a: string): string // last signature
function foo(a: number | string): number | string {
return null as any
}
type Fn = typeof foo
// returns last overloaded signature
type Arguments = Parameters<Fn> // [a: string]
Parameters
always returns last overdloaded signature of function.
Try to change the order:
function foo(a: string): string
function foo(a: number): number// last signature
function foo(a: number | string): number | string {
return null as any
}
type Fn = typeof foo
// returns last overloaded signature
type Arguments = Parameters<Fn> // [a: number]
There is no way to return a union of all parameters because it is unsound. See official explanation here
It's not really possible to make this in a way that's both useful and sound. Consider a function like
declare function fn(n1: number, n2: number): void; declare function doCall<T extends (a1: any, a2: any) => void>(func: T, a0: Parameters<T>[0], a1: Parameters<T>[1]): void; ```
If
Parameters<T>[0]
returnsstring | number
, thendoCall(fn, 0, "")
would incorrectly succeed. IfParameters<T>[0]>
returnsstring & number
, thendoCall(fn, 0, 0)
would incorrectly fail (and be a big breaking change). Notably, with conditional types and unions, really the only kind of functions that can't be typed with a single overload are exactly the ones that have this failure mode.
The current behavior at least makes it so that some calls are correctly accepted.
You can find some workarounds in above github thread