Typescript / Request-Promise:无法调用类型缺少呼叫签名的表达式

时间:2018-07-17 01:07:16

标签: typescript request-promise

我有一个服务器端点,我想返回异步请求或承诺拒绝Promise.reject('error message')的结果,但是当我向函数中添加Promise.reject而不是仅仅返回异步请求时,出现此错误:

Cannot invoke an expression whose type lacks a call signature. Type '{ <U>(onFulfill?: (value: any) => U | PromiseLike<U>, onReject?: (error: any) => U | PromiseLike<...' has no compatible call signatures.

我很困惑,因为Promise.reject有一个then方法。这是代码:

const funcThatReturnsPromise = (data) => {
    const validatedData = validateKeyData(data)
    if(validatedData) {
      return request.post({
        url: '/apiurl',
        json: true,
        body: validatedData
      })
    } else {
      return Promise.reject('TESTING rejected')
    }
}

const funcThatDoesWork = ((req, res) => {
    return funcThatReturnsPromise(req.body)
    .then(data => {
       if(data) {
         const theId = data.id
         const fullData = { ...req.body, theId }
       }
    })
    .catch(error => {
       console.log('ERROR', error)
       res.status(500).send({code: 'unknown', message: error})
    })
 })

1 个答案:

答案 0 :(得分:0)

由于RequestPromise基于Bluebird的Promise<any>,但与之不相同,因此funcThatReturnsPromise实际上返回联合类型RequestPromise | Promise<never>,该联合类型没有必需的then的调用签名(它有两个签名,分别输入,并且编译器不能一次调用两者)。

以下简单代码中也会出现相同的问题:

const prom = Math.random() > 0.5 ? Promise.resolve(true) : Promise.resolve(0);
// prom has a type Promise<number> | Promise<boolean>
prom.then(data => { const test = 1; }); // error: then() is ambiguous

我发现了两种处理方法:

  1. (不是类型安全的)只需声明被拒绝的承诺为Promise<any>

    const funcThatReturnsPromise = (data) => {
         const validatedData = validateKeyData(data)
         if(validatedData) {
           return request.post({
             url: '/apiurl',
             json: true,
             body: validatedData
           })
         } else {
           return Promise.reject('TESTING rejected') as Promise<any>
         }
     }
    
  2. (类型安全)为两个返回值进行正确的键入。会是这样的:

    const funcThatReturnsPromise = (data) => {
        const validatedData = validateKeyData(data)
        if(validatedData) {
          return request.post({
            url: '/apiurl',
            json: true,
            body: validatedData
          }) as Partial<Promise<ResultType>> & Pick<Promise<ResultType>, 'then' | 'catch'>
        } else {
          return Promise.reject('TESTING rejected') as Promise<ResultType>
        }
    }
    

ResultType在哪里……好,我们正在等待的typeof数据。
请注意,我们不能仅仅将request.post({...})断言为Promise<ResultType>,因为RequestPromise没有提供完整的Promise API,但是我们可以强制编译器至少知道then的方法catchPromise在这里(可能还有其他方法)。