我该如何键入一个包装了promise保证功能的函数,并返回该oringal函数的类型?

时间:2019-03-13 14:10:02

标签: typescript

我不确定标题是否有意义,因此我认为最好举个例子。想法是,此函数采用1参数,这是一个promise返回函数,而wrapping函数将返回一个对象,这将允许我取消promise。

这是我所拥有的:

export interface ICancelablePromise<T> {
  cancel: () => void;
  promise: Promise<T>;
}

// Trying to create a type for the makeCancelable function
export type IMakeCancelable = <T>(promiseFunc: (a?: any, b?: any, c?: any) => Promise<T>) => ICancelablePromise<T>;

const makeCancelable = <T>(promiseFunc: Promise<T>): ICancelablePromise<T> => {
  let hasCanceled = false;

  const wrappedPromise = new Promise<T>((resolve, reject) => {
    promiseFunc.then(
      (val: T) => (hasCanceled ? reject({ isCanceled: true }) : resolve(val)),
      (error: any) => (hasCanceled ? reject({ isCanceled: true }) : reject(error)),
    );
  });

  return {
    promise: wrappedPromise,
    cancel() {
      hasCanceled = true;
    },
  };
};

export default makeCancelable;

这是一个用例示例:

const wrappedFetchApi = makeCancelable(fetchApi(SOME_URL));

wrappedFetchApi.promise.then(apiResponse => /* DO SOMETHING */);

OR

wrappedFetchApi.cancel();

到目前为止,通过输入,我不断收到错误消息:

没有为签名'(promiseFunc:(a ?: any,b ?: any,c ?: any)=> Promise):ICancelablePromise

1 个答案:

答案 0 :(得分:1)

正如Stefan Neubert所提到的,您的代码中存在不一致之处,我不确定您的身份。但是我最好的猜测是您想创建一个高阶函数,该函数需要一个Promise工厂并返回一个ICancelablePromise工厂

所以...

let delay = (ms: number) => new Promise(r => setTimeout(r, ms));
let delayCancellable = makeCancelable(delay);
delayCancellable(1000); // return a ICancelablePromise

这是您的操作方法...

interface ICancelablePromise<T> {
  cancel: () => void;
  promise: Promise<T>;
}

function makeCancelable<T, A extends any[]>(promiseFunc: (...args: A) => Promise<T>): (...args: A) => ICancelablePromise<T> {
    return (...args: A): ICancelablePromise<T> => {
        let hasCanceled = false;

        const wrappedPromise = new Promise<T>((resolve, reject) => {
            promiseFunc(...args).then(
                (val: T) => (hasCanceled ? reject({ isCanceled: true }) : resolve(val)),
                (error: any) => (hasCanceled ? reject({ isCanceled: true }) : reject(error)),
            );
        });

        return {
            promise: wrappedPromise,
            cancel() {
                hasCanceled = true;
            },
        };    
    }
};

let delay = (time: number) => new Promise<{ test: string }>(resolve => {
    setTimeout(() => {
        resolve({ test: "foo" });
    }, time);
})
let delayCancellable = makeCancelable(delay);


let delayed = delayCancellable(1000);
delayed.promise
.then(val => {
    console.log(val.test)
    console.log(val.foo) // <-- error
})
.catch(() => console.log("rejected"))

delayed.cancel();

/*
all these will give compile error because
their args don't match delay's args
*/

delayCancellable()
delayCancellable("hello")

/*these will also give an error because they are
not promise returning functions*/

makeCancelable(() => alert("foo"))
makeCancelable(123)

这里是demo(您也可以删除编译错误,然后点击“运行”以测试实现)