Можно ли извлечь типы параметров функции из объекта в виде кортежей? - PullRequest
0 голосов
/ 20 ноября 2018

Например, у меня есть какой-то объект с функциями

{
 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 голосов
/ 20 ноября 2018

Как примечание, для версии с одним параметром вам не нужно 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}

Для нескольких параметров вам нужно будет использовать условные типы для извлечения параметров (и это возможно только в 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]
...