【问题标题】:Typescript: typing a function with an array of functions that returns an array of each function return type打字稿:使用函数数组输入函数,该函数返回每个函数返回类型的数组
【发布时间】:2021-07-05 18:49:52
【问题描述】:

下面的代码可以输入正确吗?

function arrayElementTypes(...array: Array<(() => string) | (() => number) | (() => {prop: string}) | (() => number[])>) {
   /// .. do something
   /// .. and then return an array with each functions result
   return array.map(arg => arg())
}

const [varA, varB, varC] = arrayElementTypes( () => "", () => ({prop: "prop"}), () => [1,2,3] )
// how can this be typed appropriately so that the : 
// varA: string
// varB: {prop: string}
// varC: number[]

【问题讨论】:

  • 很难知道“输入正确”是什么意思。您正在传递一组具有不同参数计数的函数,因此 array.map(arg =&gt; arg()) 对于数组联合中的最后一个函数类型无效。您也只传入 3 个函数,但正在寻找一个长度为 4 的返回数组。您是否希望将返回的数组解构为单独的类型(好像它是一个元组)或函数的返回类型的交集(好像它是一个数组)?
  • 更正了示例。

标签: javascript arrays typescript typescript-generics


【解决方案1】:

设法做到了

type ReturnTypes<T extends Array<(...a: any[]) => any>> = {
  [P in keyof T]: T[P] extends (...a: any[]) => infer R ? R : never
}

type CustomArrayElement = (() => string) | (() => number) | (() => {prop: string}) | (() => number[])

function arrayElementTypes<T extends CustomArrayElement[]>(...array: T): ReturnTypes<typeof array> {
   return array.map(arg => arg())
}

const [varA, varB, varC] = arrayElementTypes( () => "", () => ({prop: "prop"}), () => [1,2,3] )

谢谢大家的帮助!!

【讨论】:

    【解决方案2】:

    我不乐观它可以正确输入。首先,我认为您正在查看 tuple,而不是数组,因为函数的“数组”具有不同的签名,并且您希望 arrayElementTypes 的返回类型对应于返回类型“数组”中的每个函数,匹配 position-wise.

    同时,我不敢说完全不可能,因为我已经看到 amazing things 可以使用泛型和条件类型的组合来完成。


    编辑:我想出了一些可能有助于最终答案的“构建块”类型,但您可以看看是否可以将它们拼凑在一起:)

    // any function
    type Fn = () => unknown;
    
    // a tuple/array of functions
    type FnArr = readonly Fn[];
    
    // the first function in your tuple of functions
    type Head<T extends FnArr> = T extends [infer HeadFn, ...any[]] ? HeadFn : never;
    
    // the rest of the functions in your tuple of functions
    type Tail<T extends FnArr> = T extends [any, ...infer TailFns] ? TailFns : never;
    

    使用上述构建块,您可以提取函数元组中每个函数的返回类型。这并不直接适用于解决方案,但也许一些递归定义的条件类型(泛化为任意函数元组)可以让你到达那里:)

    const [varA, varB, varC] = arrayElementTypes( () => "", () => ({prop: "prop"}), () => [1,2,3] )
    // how can this be typed appropriately so that the : 
    // varA: string
    // varB: {prop: string}
    // varC: number[]
    
    type ExampleFns = [ () => string, () => {prop: "prop"}, () => number[] ];
    
    type TypeForVarA = ReturnType<Head<ExampleFns>>;                // F1 = string
    type TypeForVarB = ReturnType<Head<Tail<ExampleFns>>>;          // F2 = {prop: "prop"}
    type TypeForVarC = ReturnType<Head<Tail<Tail<ExampleFns>>>>;    // F3 = number[]
    

    【讨论】:

      【解决方案3】:
      const [varA, varB, varC, varD]: Array<string | number | {prop: string} | number[]> = arrayElementTypes( () => "", () => ({prop: "prop"}), () => [1,2,3] )
      

      这是否满足您的要求?

      【讨论】:

        猜你喜欢
        • 2022-01-12
        • 2019-07-16
        • 2015-08-10
        • 1970-01-01
        • 1970-01-01
        • 2021-09-17
        • 1970-01-01
        • 2020-05-02
        • 2020-01-05
        相关资源
        最近更新 更多