首页 > 解决方案 > 如何使用工厂方法通过减少对象来获得类型推断

问题描述

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

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

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()

标签: typescript

解决方案


首先,您的错误Element implicitly has an 'any' type because type { ... } has no index signature是因为Object.keys()返回一个字符串数组apiFactories[f],并且f任何字符串都可能导致隐式结果,这在模式(特别是)any中是不允许的。您可以使用 to 的断言来解决此问题。strictnoImplicitAnyfkeyof 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(...)

推荐阅读