Добавление d.ts для функции vanilla, которая возвращает функцию, которая оборачивает функции

У меня есть сложная функция в моем ванильном коде JS (простой пример см. Ниже), который получает exportг, и я хочу добавить d.ts к этому.

До сих пор мои попытки написания .d.ts не перенаправили типы с промежуточного этапа на конечный этап

Функция / ы выглядит следующим образом (я максимально упростил ее, сохранив ту же структуру)

const factory = (x, y = 0) => {
    const z = x + y;
    return fn => {
        const p = Promise.resolve(z).then(console.warn);
        return (...args) => p.then(() => fn(...args));
    };
};

Пример использования

const A = factory(1, 2);
const fn = (a1, a2) => a1 + ' world' + a2; // (a1: string, a2: string) => string
const B = A(fn); // (i: string, j: string) => Promise<string>
B('hello', '!'); // warns 3 and returns a Promise<string> "hello world!"

Итак, как вы можете видеть из моих комментариев, типы arg ожидаемые при вызове B такой же как fn, тип возврата B Обещание типа возврата fn


Что я пробовал до сих пор

declare function factory(x: number):
    (fn: (...U: any) => T) =>
        (...U) => Promise<T>;
declare function factory(x: number, y: number):
    (fn: (...U: any) => T) =>
        (...U) => Promise<T>;

Тем не мение,

  • При взгляде на B вся информация о типах теряется fn и я остался с any[] => Promise<any> когда я ожидаю (string, string) => Promise<string>
  • Описание типа возврата дублируется несколько раз

Я также пытался писать интерфейсно-y способом, но это та же проблема с потерянными типами, и я не понимаю, как вы будете ссылаться на них

declare function factory(x: number): wrapper;
declare function factory(x: number, y: number): wrapper;
interface wrapper {
    (fn: function): wrapped;
}
interface wrapped {
    (...args: any): Promise<any>;
}

1 ответ

Решение

Вы хотите, чтобы конечная функция имела те же аргументы, что и функция, которую вы передаете в качестве параметра, если я правильно понял вопрос. Хотя вы не можете сделать это для произвольного числа параметров, вы можете определить перегрузки для функций с максимум 4 параметрами, например, и добавить больше, если они понадобятся вам позже:

declare function factory(x: number): Promiseify;
declare function factory(x: number, y: number): Promiseify;

interface Promiseify {
    <T>(fn: () => T): () => Promise<T>;
    <T, U1>(fn: (arg1: U1) => T): (arg1: U1) => Promise<T>;
    <T, U1, U2>(fn: (arg1: U1, arg2: U2) => T): (arg1: U1, arg2: U2) => Promise<T>;
    <T, U1, U2, U3>(fn: (arg1: U1, arg2: U2, arg3: U3) => T): (arg1: U1, arg2: U2, arg3: U3) => Promise<T>;
    <T, U1, U2, U3, U4>(fn: (arg1: U1, arg2: U2, arg3: U3, arg4: U4) => T): (arg1: U1, arg2: U2, arg3: U3, arg4: U4) => Promise<T>;
}
const A = factory(1, 2);
const fn = (a1: string, a2: number) => a1 + ' world' + a2; // (a1: string, a2: number) => string
const B = A(fn); // (arg1: string, arg2: number) => Promise<string>
B('hello', 1); // ok 
B('hello', '1'); // error
Другие вопросы по тегам