Typescript如果错误为空,如何键入保护承诺类型不为空

时间:2018-02-11 17:59:06

标签: typescript typescript-typings

const [err, value] = await aerr(promise())
if(!err) {
  // value should not be "possibly undefined" here
}

我在airr函数上尝试了很多疯狂的数据类型,但我无法理解错误和价值是互斥的。有什么想法吗?

如果你很好奇,这是我目前的混乱(它不起作用)

interface AErrResolve<T> {
  [0]:undefined
  [1]:T
  [Symbol.iterator](): IterableIterator<any>;
}
interface AErrReject<T> {
  [0]:any
  [1]:undefined
  [Symbol.iterator](): IterableIterator<any>;
}
export function aerr<T>(promise:Promise<T>) {
  return promise.then((x:T):AErrResolve<T> => [undefined, x]).catch((err:any):AErrReject<T> => [err, undefined])
}

1 个答案:

答案 0 :(得分:3)

嗯,我不认为TypeScript会帮助你按照自己的方式做到这一点。看起来您希望编译器执行control flow type analysis以了解确切地定义[err, value]的一个元素。

有几个原因导致这种情况无法奏效。您希望[undefined, T] | [any, undefined]充当discriminated union,其中位于键0的属性值用作判别属性。这是一个问题,因为TypeScript目前only supports discriminating values which are finite typesany是无限的。这也是一个问题,因为要检查键0,您必须使用括号表示法而不是点表示法,但TypeScript当前为will not apply discriminated union narrowing when you use bracket notation。最后,即使你可以让它工作,你在检查判别属性之前对元组进行解构,并期望类型缩小仍然发生,但显然too much for TypeScript to handle

如果我解决了所有这三个问题,我会得到一些有效但与你正在寻找的东西完全不同的东西:

interface AErrResolve<T> {
    type: 'resolved'
    value: T
}
interface AErrReject {
   type: 'rejected'
   err: any
}

declare function aerr<T>(promise: Promise<T>): AErrResolve<T> | AErrReject

async function foo<T>(promise: () => Promise<T>) {
    const result = await aerr(promise())
    if (result.type === 'resolved') {
        result.value // okay
    } else {
        result.err // okay
    }
}

这很有效,但我不知道它是否适合您的使用案例。它取决于你。无论如何,希望这对你有所帮助。祝你好运。