动态地将函数放入对象中而不会丢失类型信息

时间:2019-05-29 15:32:25

标签: typescript types

在我的functions.ts中,我定义了2个函数,都带有一个api对象,并返回一个具有不同arg类型,arg数字和返回类型的函数。

export function f1 (api: Api) {
  return function (a: number): number[] {/* not important */}
};
export function f2 (api: Api) {
  return function (a: string, b: string): boolean {/* not important */}
};

现在给定一个api: Api全局对象,我想定义一个对象,该对象具有字段f1f2,并且与每个字段关联的值是上述内部的内部函数2个功能。

也就是说,我会手动进行:

const api: Api = ...;
const myObject = {
  f1: f1(api),
  f2: f2(api),
}

这很好用。

但是下一步:我希望动态地做到这一点,即无需手动输入f1和f2。

这是我的起点:

import * as functions from './functions';

const api: Api = ...;
const myObject = Object.keys(functions).reduce((accumulator, functionName) => {
  accumulator[functionName] = functions[functionName](api);
}, {} as ???);

该代码有效,但键入无效。我不确定要放什么而不是???{[index: keyof typeof functions]: (...args: any[]) => any}可以使用,但是我丢失了很多有关类型的信息。

我尝试查看TS的Parameters<T>ReturnType<T>,但我敢肯定infer可以完成一些工作,但似乎无法掌握。

1 个答案:

答案 0 :(得分:1)

  

该代码有效,但键入无效。我不确定要放什么而不是???。

这是一种可行的方法。它创建一个新类型,将每个函数名称映射到其返回类型。

type ReturnTypes<T> = {
    [K in keyof T]: T[K] extends (...args: any) => any
    ? ReturnType<T[K]>
    : never;
};

const myObject = Object
    .keys(functions)
    .reduce(
        (accumulator, functionName) => {
            accumulator[functionName] = functions[functionName](api);
            return accumulator;
        },
        {} as ReturnTypes<typeof functions>
    );

const result1: number[] = myObject.f1(10);
const result2: boolean = myObject.f2('foo', 'bar');

它在TypeScript playground中。