如何通过使用工厂方法减少对象来进行类型推断

时间:2018-05-01 19:20:23

标签: typescript

我试图让TypeScript了解我的reduce的结果并保持原始输入的工厂方法的结果。现在我得到Element implicitly has an 'any' type because type '{ fetchSomething: (i: number) => (query: SomethingQuery) => Promise<{ [s: string]: string; }[]>; ...' has no index signature.

我的generateApiMethods函数的结果与apiFactories对象文字的结果相同,但已定义i。我知道下面的代码不能正确输入,我只是不知道如何正确推断TypeScript。

import { request } from "./helpers"

const apiFactories = {
  fetchSomething: (i: number) =>
    (query: Api.SomethingQuery): Promise<Api.SomethingResponse> =>
      request(i, "/something", query),
  fetchSomeOtherThing: (i: number) => 
    (id: number): Promise<Api.SomeOtherThingResponse> =>
      request(i, `/someotherthing/${id}`)
};

const generateApiMethods = () =>
  Object.keys(apiFactories).reduce(
    (acc, f, i) => ({ ...acc, [f]: apiFactories[f](i) }),
    {}
  );

export const api = generateApiMethods()

1 个答案:

答案 0 :(得分:1)

首先,您的错误Element implicitly has an 'any' type because type { ... } has no index signature是因为Object.keys() returns an array of stringsapiFactories[f] f可能是任何字符串导致隐式any结果,在strict模式下禁止使用(具体为noImplicitAny)。您可以使用fkeyof typeof apiFactories的断言来解决此问题。

除此之外,我认为reduce()无法推断出你想要的东西。您正在传递{}作为初始值,因此返回类型被推断为{}。也就是说,您可以使用地图类型来描述您的API:

type ApiFactories = typeof apiFactories;
type Api = { [P in keyof ApiFactories]: ReturnType<ApiFactories[P]> };

现在你可以将初始值断言为Api,和/或将类型参数传递给reduce<Api>(),你应该得到你想要的对象类型:

const generateApiMethods = () =>
  Object.keys(apiFactories).reduce(
    (acc, f, i) => ({ ...acc, [f]: apiFactories[f as keyof Api](i) }),
    {} as Api
  );

const api = generateApiMethods();
api.fetchSomething(query).then(...)
api.fetchSomeOtherThing(123).then(...)