我有一个服务器端点,我想返回异步请求或承诺拒绝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})
})
})
答案 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
我发现了两种处理方法:
(不是类型安全的)只需声明被拒绝的承诺为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>
}
}
(类型安全)为两个返回值进行正确的键入。会是这样的:
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
的方法catch
和Promise
在这里(可能还有其他方法)。