Как получить логический вывод типа через Reduce на объект с помощью фабричных методов - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь заставить TypeScript понять результат моего сокращения и придерживаться исходных типов для результата моих фабричных методов. Прямо сейчас я получаю 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 голосов
/ 02 мая 2018

Прежде всего, ваша ошибка Element implicitly has an 'any' type because type { ... } has no index signature связана с тем, что Object.keys() возвращает массив строк , а apiFactories[f], где f может быть любой строкой, приводящей к неявному any результату, что запрещено в режиме strict (в частности, noImplicitAny). Вы можете исправить это с утверждением от f до keyof 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(...)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...