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])
}
答案 0 :(得分:3)
嗯,我不认为TypeScript会帮助你按照自己的方式做到这一点。看起来您希望编译器执行control flow type analysis以了解确切地定义[err, value]
的一个元素。
有几个原因导致这种情况无法奏效。您希望[undefined, T] | [any, undefined]
充当discriminated union,其中位于键0
的属性值用作判别属性。这是一个问题,因为TypeScript目前only supports discriminating values which are finite types和any
是无限的。这也是一个问题,因为要检查键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
}
}
这很有效,但我不知道它是否适合您的使用案例。它取决于你。无论如何,希望这对你有所帮助。祝你好运。