添加 `finally` 时,Typed Promise 将 return 类型更改为未知

Typed Promise changes return type to unknown when `finally` is added

我有一个静态类型 return 类型的常规承诺:

export const hasActiveSubscription = (whatEver: string): Promise<string> => 
  new Promise((resolve, reject) => {
    if (true){
      resolve('imastring')
    }
    reject(new Error('nope'))
  })

到目前为止一切顺利,但如果我添加一个 finally 块,它将 return 类型更改为 unknown 并且无法传递该字符串类型,例如

export const hasActiveSubscription = (whatEver: string): Promise<string> => 
  new Promise((resolve, reject) => {
    if (true){
      resolve('imastring')
    }
    reject(new Error('nope'))
  }).finally(console.info)

Type 'Promise' is not assignable to type 'Promise'.
Type 'unknown' is not assignable to type 'string'.

如何在保留 finally 块的同时保留原始 return 类型?

如果有帮助,我的实际代码有一个 setTimeout(以确保此函数不会花费太长时间 return),我想在 finally 上清除超时,而不是清除 5 个不同位置的超时。

如果您从函数签名的 return 位置删除类型注释,您会注意到实际的 return 类型是 Promise<unknown>,而不是 Promise<string>如您所料,这构成了错误的第一部分:

const hasActiveSubscription: (whatEver: string) => Promise<unknown>;

Promise是一个泛型接口,其finally方法在其return类型注解中使用接口的类型参数(示例来自ES2018 lib):

interface Promise<T> {
    finally(onfinally?: (() => void) | undefined | null): Promise<T>
}

你只需要指定构造的Promise的类型,一切就OK了:

export const hasActiveSubscription = (whatEver: string) => 
  new Promise<string>((resolve, reject) => {
    if (true){
      resolve('imastring')
    }
    reject(new Error('nope'))
  }).finally(console.info) //no error, Promise<string> is inferred

Playground


注意事项 - 您的示例在 reject 调用

中有一个不匹配的括号