是否可以从对象中提取功能参数类型为元组?

时间:2018-11-20 17:31:49

标签: typescript mapped-types

例如,我有一些带有功能的对象

{
 fnNumber: (x: number) => x,
 fnString: (x: string) => x
}

我想创建这种类型

{ 
  fnNumber: number,
  fnString: string
}

我可以这样做

type FnParam<T> = {[key in keyof T ]: T[key]}
type FnObject<T> = {[key in keyof T]: (x: T[key]) => any}

export function create<T>(x: FnObject<T>): FnParam<T> {
 return {} as any
}

const types = create({
 fnNumber: (x: number) => x,
 fnString: (x: string) => x
})
types: : {fnNumber: number, fnString: string}

但是如果函数具有多个参数

{
 fnNumber: (x: number, y: string) => x,
 fnString: (x: string) => x
}

我需要创建元组

{ 
  fnNumber: [number, string],
  fnString: [string]
}

类似这样的东西

type FnParam2<T> = {[key in keyof T ]: T[key]}
type FnObject2<T> = {[key in keyof T]: (...x: T[key]) => any}

export function create2<T>(x: FnObject2<T>): FnParam2<T> {
 return {} as any
}

但是打字稿不能从...x: T[key]推断元组

有可能吗?

1 个答案:

答案 0 :(得分:1)

请注意,对于您的单个参数版本,您不需要FnParams,只需使用T。这将产生相同的结果:

export function create<T>(x: FnObject<T>): T {
 return {} as any
}

const types = create({
 fnNumber: (x: number) => x,
 fnString: (x: string) => x
})
// types: : {fnNumber: number, fnString: string}

对于多个参数,您将需要使用conditional types来提取参数(并且只有在引入Tuples in rest parameters and spread expressions之后的Typescript 3.0或更高版本中才有可能)。

type ArgumentTypes<T> = T extends (...a: infer A) => void ? A : never 
type FnParam<T> = { [key in keyof T]: ArgumentTypes<T[key]> }
type FnObject<T> = Record<string, (...a: any[]) => any>

export function create<T extends FnObject<any>>(x: T): FnParam<T> {
    return {} as any
}

const types = create({
    fnNumber: (x: number, y: string) => x,
    fnString: (x: string) => x
})

types.fnNumber // [number, string]
types.fnString // [string]