1

我有一个服务器端点,我想返回异步请求的结果或承诺拒绝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})
    })
 })
4

1 回答 1

0

由于RequestPromise基于Promise<any>Bluebird,但与它不同,它funcThatReturnsPromise真正返回 union type 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({...})as Promise<ResultType>,因为RequestPromise它不提供完整的PromiseAPI,但我们可以强制编译器知道至少方法thencatchofPromise在这里(可能还有其他东西)。

于 2018-07-17T03:23:02.297 回答