【问题标题】:Infer typeof nested function based on callback基于回调推断嵌套函数的typeof
【发布时间】:2021-02-17 00:43:59
【问题描述】:

我正在尝试编写一个接受对象并返回嵌套函数的函数,该函数将接受回调并返回相同类型的函数。不幸的是,我无法以这种方式编写它,因此结果将具有与回调相同的类型

type Constructor<T> = new (...args: any[]) => T


export type Settings = {
   maxCalls: number
   interval: number
   errors: Constructor<Error>[]
}

export function withRetryDelayed<R, U extends any[]>({
   maxCalls = 2,
   interval = 100,
   errors = [Error]
}: Partial<Settings> = {}): (cb: (...args: U) => Promise<R>) => (...args: U) => Promise<R> {
   let calls = maxCalls
   return (callback: (...args: U) => Promise<R>): (...args: U) => Promise<R> => {
      const retrying = async (...args: U): Promise<R> => {
         try {
            return await callback(...args)
         } catch (err) {
            if (calls-- <= 1 || !errors.some(ErrorConstructor => err instanceof ErrorConstructor)) {
               throw err
            }
            return interval
               ? new Promise(resolve => {
                  setTimeout(() => resolve(retrying(...args)), (maxCalls - calls) * interval)
               })
               : retrying(...args)
         }
      }
      return retrying
   }
}

const theX = (a: string): Promise<string> => Promise.resolve(a)

class MockError1 extends Error { }



const withRetryCallback = withRetryDelayed({
   maxCalls: 10,
   errors: [MockError1]
})(theX)


// typeof withRetryCallback is (...args: any[]) => Promise<unknown>

Playground

【问题讨论】:

    标签: typescript


    【解决方案1】:

    只需在应用它们时添加泛型 - 在内部函数而不是外部函数上。这样您在应用设置后获得的功能是通用的,并且可以根据您提供的参数进行推断。

    
    type Constructor<T> = new (...args: any[]) => T
    
    
    export type Settings = {
       maxCalls: number
       interval: number
       errors: Constructor<Error>[]
    }
    
    export function withRetryDelayed({
       maxCalls = 2,
       interval = 100,
       errors = [Error]
    }: Partial<Settings> = {}) {
       let calls = maxCalls
       return <R, U extends any[]>(callback: (...args: U) => Promise<R>): (...args: U) => Promise<R> => {
          const retrying = async (...args: U): Promise<R> => {
             try {
                return await callback(...args)
             } catch (err) {
                if (calls-- <= 1 || !errors.some(ErrorConstructor => err instanceof ErrorConstructor)) {
                   throw err
                }
                return interval
                   ? new Promise(resolve => {
                      setTimeout(() => resolve(retrying(...args)), (maxCalls - calls) * interval)
                   })
                   : retrying(...args)
             }
          }
          return retrying
       }
    }
    
    const theX = (a: string): Promise<string> => Promise.resolve(a)
    
    class MockError1 extends Error { }
    
    const withRetryCallback = withRetryDelayed({
       maxCalls: 10,
       errors: [MockError1]
    })(theX);
    
    // Now typeof withRetryCallback is (a: string) => Promise<string>
    
    

    【讨论】:

    • 非常感谢!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2011-05-11
    • 2013-03-19
    • 2019-10-29
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    相关资源
    最近更新 更多