我有一个返回元组联合的函数,看起来无论我做什么,flow都无法选择其中一个元组。示例(try flow link):
declare function genNumber(): [Error, null] | [null, number];
const [err, num] = genNumber();
if (err) {
throw err;
}
// num should now be a number, but I can't convince flow of this
(num: number);
最后一行的num
显然应该是number
但流量仍然认为它是null | number
。我有几个解决方法,即将错误检查转换为if (!num) {
,或者只是生成函数谎言并将返回类型更改为[Error, ((null: any): number)] | [null, number]
但我真的很讨厌这两个。
我认为你的问题是对结果进行解构,因为分析无法确定哪种返回类型适用。文档“Disjoint unions with exact types”中涵盖了一个可能的解决方案,你在第二个例子(Try it here)中实现了类似的东西。
type Success = {| success: false, error: Error |}
type Failure = {| success: true, num: number |}
declare function genNumber(): Success | Failure;
const result = genNumber();
if (!result.success) {
throw result.error;
}
// num should now be a number
(result.num: number);
更新:目前似乎无法在流中处理节点样式回调(Github issue)。
以下是如何定义节点回调(Try):
type Completion = (err: ?Error, result: ?number) => void;
function myFunc(done: Completion) {
done(null, 1);
}
myFunc((err, result) => {
if (err) throw err;
if (result) (result: number);
});
以下是你的元组如何定义(Try):
declare function genNumber(): [?Error, ?number];
const [err, num] = genNumber();
if (err) {
throw err;
}
if (num) {
(num: number);
}
虽然这仍然没有你想象的那么干净。我无法让Flow尝试传递一个版本的Promise作为输入和返回类型,它似乎不喜欢await
关键字(Try)。
async function gen<T>(promise: Promise<T> | T): Promise<[?Error, ?T]> {
return new Promise((resolve, reject) => {
Promise.all([promise])
.then(result => resolve([null, result[0]]))
.catch(e => reject([e, null]));
});
}
const [ err, num ] = await gen(1);
if (err) throw err;
if (num) (num:number);