访问联合类型属性的惯用方式
Idiomatic way to access properties of union type
访问联合类型中合并的类型之一可能缺少的属性的惯用方法是什么?
type DataColumn = {
value: number;
};
type CalculatedColumn = {
calculation: string;
};
type Column = DataColumn | CalculatedColumn;
function getValue(c: Column) {
return c.value || c.calculation;
}
流 typecheck 导致以下错误:
13: return c.value || c.calculation;
^ property `calculation`. Property not found in
13: return c.value || c.calculation;
^ object type
@dfkaye 在 twitter 上指出,如果 "default" 案例抛出错误,它会起作用:
function e() {
throw new Error('foo');
}
function getValue(c: Column) {
return c.value || c.calculation || e();
}
谁能解释一下:
- 为什么有效?是故意的还是副作用?
- 为什么有必要?列类型总是
value
或 calculation
,因此永远不会发生错误情况。
- 是否有更好、更惯用的方法?
- 这是一种安全的方法吗,还是将来可能会失效?
PS:似乎在 TypeScript it can be done 中使用类型断言。
惯用的方法是使用 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'});
我不确定为什么你描述的情况不起作用。我想不出任何不健全的理由。但是不相交的工会确实有效。
Why it works? Is it intentional, or a side effect?
这很可能是一个错误,Flow simple 忽略所有分支,但最后:
function getValue(c: Column) {
return c.value || c.calculation || undefined;
}
Why is it necessary? Column type has always either value or calculation, so error case should never happen
这就是你错的地方。如果值具有类型 { value: number }
,则意味着它可以具有任何类型的任何其他 属性,包括类型 string
的 calculation
或可能是其他类型。
Is there a better, more idiomatic way?
是的,请参阅 Nat Mote 的回答
Is this a safe approach, or is it likely to break in future?
原则上不安全,以后很可能坏掉
Seems like in TypeScript it can be done using type assertions.
您可以在 Flow 中做同样的事情,但它不安全:
function getValue(c: Column) {
return ((c: any): DataColumn).value || ((c: any): CalculatedColumn).calculation;
}
另外你不要忘记数字和字符串可以是假的。
访问联合类型中合并的类型之一可能缺少的属性的惯用方法是什么?
type DataColumn = {
value: number;
};
type CalculatedColumn = {
calculation: string;
};
type Column = DataColumn | CalculatedColumn;
function getValue(c: Column) {
return c.value || c.calculation;
}
流 typecheck 导致以下错误:
13: return c.value || c.calculation;
^ property `calculation`. Property not found in
13: return c.value || c.calculation;
^ object type
@dfkaye 在 twitter 上指出,如果 "default" 案例抛出错误,它会起作用:
function e() {
throw new Error('foo');
}
function getValue(c: Column) {
return c.value || c.calculation || e();
}
谁能解释一下:
- 为什么有效?是故意的还是副作用?
- 为什么有必要?列类型总是
value
或calculation
,因此永远不会发生错误情况。 - 是否有更好、更惯用的方法?
- 这是一种安全的方法吗,还是将来可能会失效?
PS:似乎在 TypeScript it can be done 中使用类型断言。
惯用的方法是使用 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'});
我不确定为什么你描述的情况不起作用。我想不出任何不健全的理由。但是不相交的工会确实有效。
Why it works? Is it intentional, or a side effect?
这很可能是一个错误,Flow simple 忽略所有分支,但最后:
function getValue(c: Column) {
return c.value || c.calculation || undefined;
}
Why is it necessary? Column type has always either value or calculation, so error case should never happen
这就是你错的地方。如果值具有类型 { value: number }
,则意味着它可以具有任何类型的任何其他 属性,包括类型 string
的 calculation
或可能是其他类型。
Is there a better, more idiomatic way?
是的,请参阅 Nat Mote 的回答
Is this a safe approach, or is it likely to break in future?
原则上不安全,以后很可能坏掉
Seems like in TypeScript it can be done using type assertions.
您可以在 Flow 中做同样的事情,但它不安全:
function getValue(c: Column) {
return ((c: any): DataColumn).value || ((c: any): CalculatedColumn).calculation;
}
另外你不要忘记数字和字符串可以是假的。