Динамическое размещение функций в объекте без потери информации о типе

В моем functions.ts я определяю 2 функции, обе принимают объект api и возвращают функцию с разными типами аргументов, номерами аргументов и типами возвращаемых значений.

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, я хочу определить объект, который имеет поля f1 и f2, а значение, связанное с каждым полем, является внутренней функцией внутри двух вышеуказанных функций.

А именно, вручную я бы сделал:

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} сработает, но я теряю много информации о типах.

Я пытался смотреть на ТС Parameters<T>, ReturnType<T> и уверен, что с infer можно что-то сделать, но не могу понять.

Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
1
0
22
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

The code works, but the typings don't. I'm not sure what to put instead of ???.

Вот подход, который работает. Он создает новый тип, который сопоставляет каждое имя функции с типом возвращаемого значения.

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.

Хороший! Не могли бы вы поправить ссылку на игровую площадку, я посмотрю

jeanpaul62 29.05.2019 18:29

Исправлена ​​ссылка на игровую площадку.

Shaun Luttin 29.05.2019 18:32

Другие вопросы по теме