Given an overloaded function example
.
function example(a: string): number
function example(a: string, b?: string): number {
return 1
}
type
It is not possible. To quote 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.
In your case, you have only one overload, as jonrsharpe points out correctly. Say, we add one for illustration:
function example(a: string): number
function example(a: string, b: string): number
function example(a: string, b?: string): number {
return 1
}
Then the conditional type Parameters
will always infer/pick the last overload (sample here):
type Result = Parameters<typeof example> // Result = [string, string]
In the answers to the question this duplicates the limitation mentioned in @ford04's answer here, that infer
only looks at the last overloaded signature, is acknowledged.
But this answer shows it's not completely impossible; you can tease out some information about overloads, at least for functions with up to some arbitrary fixed number of them. But it's hairy and ugly and there might be bugs in it, see microsoft/TypeScript#28867. Here's one way of doing it:
type Overloads<T> =
T extends {
(...args: infer A1): infer R1; (...args: infer A2): infer R2;
(...args: infer A3): infer R3; (...args: infer A4): infer R4
} ? [
(...args: A1) => R1, (...args: A2) => R2,
(...args: A3) => R3, (...args: A4) => R4
] : T extends {
(...args: infer A1): infer R1; (...args: infer A2): infer R2;
(...args: infer A3): infer R3
} ? [
(...args: A1) => R1, (...args: A2) => R2,
(...args: A3) => R3
] : T extends {
(...args: infer A1): infer R1; (...args: infer A2): infer R2
} ? [
(...args: A1) => R1, (...args: A2) => R2
] : T extends {
(...args: infer A1): infer R1
} ? [
(...args: A1) => R1
] : any
type OverloadedParameters<T> =
Overloads<T> extends infer O ?
{ [K in keyof O]: Parameters<Extract<O[K], (...args: any) => any>> } : never
type OverloadedReturnType<T> =
Overloads<T> extends infer O ?
{ [K in keyof O]: ReturnType<Extract<O[K], (...args: any) => any>> } : never
The Overloads<T>
type alias takes a function type T
and returns a tuple of its call signatures (for up to four overloads). And OverloadedParameters<T>
and OverloadedReturnType<T>
map Parameters<T>
and ReturnType<T>
over that tuple, respectively.
Let's see it in action (after correcting your example so that it actually has multiple overloads, as done in the other answer):
function example(a: string): number
function example(a: string, b: string): number
function example(a: string, b?: string): number {
return 1
}
type ExampleOverloads = Overloads<typeof example>
// type ExampleOverloads = [(a: string) => number, (a: string, b: string) => number]
type ExampleParameters = OverloadedParameters<typeof example>
// type ExampleParameters = [[string], [string, string]]
Looks reasonable to me. Okay, hope that helps; good luck!
Link to code