为vanilla函数添加d.ts,返回一个包装函数的函数

时间:2018-03-31 19:18:03

标签: javascript typescript .d.ts

我的vanilla JS代码中有一个复杂的函数(稍后会看到简单示例)得到export d,我想为它添加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!"

从您的评论中可以看出,调用B时预期的arg类型与fn相同,B的返回类型是 Promise 的返回类型为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>
  • 返回类型的描述多次重复

我也试过以界面的方式写作,但这有类型迷路的问题,我不知道你如何引用它们

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 个答案:

答案 0 :(得分:2)

如果我正确理解了问题,您希望最终函数具有与作为参数传递的函数相同的参数。虽然您无法为任意数量的参数执行此操作,但您可以为具有最多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