重载函数的通用参数并不包含所有选项

时间:2019-12-30 19:34:26

标签: typescript generics parameters

给出一个重载函数example

function example(a: string): number
function example(a: string, b?: string): number { 
  return 1
}

type Result = Parameters<typeof example>

我希望Result包含example的参数的所有选项,而不仅仅是第一个/最顶部的参数集。如何获取参数?

2 个答案:

答案 0 :(得分:2)

在对the question this duplicates的限制中,承认infer仅看最后一个重载签名。

但是@ford04's answer here表明不是完全不可能;您可以从中获取一些有关重载的信息,至少对于具有最多任意固定数目的函数而言。但这是多毛且丑陋的,this answer。这是一种实现方式:

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

Overloads<T>类型的别名采用函数类型T并返回其调用签名的元组(最多四个重载)。 OverloadedParameters<T>OverloadedReturnType<T>分别在该元组上映射Parameters<T>ReturnType<T>

让我们看看它的作用(在更正示例之后,如在另一个答案中所做的那样,它实际上具有多个重载):

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]]

我觉得合理。好的,希望能有所帮助;祝你好运!

there might be bugs in it, see microsoft/TypeScript#28867

答案 1 :(得分:0)

不可能。引用docs

  

从具有多个调用签名的类型(例如重载函数的类型)进行推断时,将根据最后一个签名(可能是最宽松的情况)进行推断。无法基于参数类型列表执行重载解析。

在您的情况下,正如jonrsharpe正确指出的那样,您只有一个重载。说,我们添加一个用于说明:

function example(a: string): number
function example(a: string, b: string): number
function example(a: string, b?: string): number { 
  return 1
}

然后条件类型Parameters将始终推断/选择上一个重载(sample here):

type Result = Parameters<typeof example> // Result = [string, string]