访问union中合并的其中一种类型中可能缺少的union类型属性的惯用方法是什么?
type DataColumn = {
value: number;
};
type CalculatedColumn = {
calculation: string;
};
type Column = DataColumn | CalculatedColumn;
function getValue(c: Column) {
return c.value || c.calculation;
}
Flow typecheck会导致以下错误:
13: return c.value || c.calculation;
^ property `calculation`. Property not found in
13: return c.value || c.calculation;
^ object type
@dfkaye在Twitter上指出,如果“默认”情况引发错误,则可行:
function e() {
throw new Error('foo');
}
function getValue(c: Column) {
return c.value || c.calculation || e();
}
有人可以解释一下:
value
或calculation
,因此不应出现错误情况。PS:似乎在TypeScript it can be done中使用类型断言。
答案 0 :(得分:3)
惯用法是使用disjoint unions。这传递没有错误:
type DataColumn = {
kind: 'data';
value: number;
};
type CalculatedColumn = {
kind: 'calculated';
calculation: string;
};
type Column = DataColumn | CalculatedColumn;
function e() {
throw new Error('foo');
}
function getValue(c: Column) {
return c.kind === 'data' ? c.value : c.calculation;
}
getValue({kind: 'data', value: 123});
getValue({kind: 'calculated', calculation: 'foo'});
我真的不确定为什么你描述的案例不起作用。我无法想出任何不合理的理由。但不相交的工会肯定有效。
答案 1 :(得分:2)
为什么会这样?这是故意还是副作用?
它很可能是一个错误,Flow简单忽略所有分支但最后:
function getValue(c: Column) {
return c.value || c.calculation || undefined;
}
为什么有必要?列类型始终是值或计算,因此错误情况永远不会发生
这是你错的地方。如果值的类型为{ value: number }
,则表示它可以包含任何类型的任何其他属性,包括类型为calculation
的{{1}},或者可能属于其他类型。
是否有更好,更惯用的方式?
是的,请参阅Nat Mote的回答
这是一种安全的方法,还是将来可能会破裂?
原则上它不安全,所以它很有可能在未来破裂
在TypeScript中似乎可以使用类型断言来完成。
你可以在Flow中做同样的事情,但它不安全:
string
另外你不应该忘记数字和字符串可能是假的。