2016-11-29 68 views
2

访问工会中合并类型之一中可能缺少的工会类型属性的惯用方式是什么?访问工会类型属性的地道方式

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上,如果有抛出的 “默认” 情况下的错误,它的工作原理:

function e() { 
    throw new Error('foo'); 
} 

function getValue(c: Column) { 
    return c.value || c.calculation || e(); 
} 

有人可以解释一下:

  1. 为什么它有效?是故意的还是副作用?
  2. 为什么有必要?列类型始终为valuecalculation,因此应该不会发生错误情况。
  3. 有更好,更习惯的方法吗?
  4. 这是一种安全的方法,还是未来可能会破裂?

PS:看起来像TypeScript it can be done使用类型断言。

回答

1

Why it works? Is it intentional, or a side effect?

这很可能是一个错误,流程简单忽略所有的分支,但最后:

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 },则表示它可以具有任何类型的任何其他属性,包括类型为stringcalculation,或者可以是某种其他类型的属性。

Is there a better, more idiomatic way?

是的,去看纳特莫特的回答

Is this a safe approach, or is it likely to break in future?

这不是原则上的安全,所以很可能在未来

Seems like in TypeScript it can be done using type assertions.

打破你可以做同样的事情在流,但它是不安全的:

function getValue(c: Column) { 
    return ((c: any): DataColumn).value || ((c: any): CalculatedColumn).calculation; 
} 

此外,你不应该忘记,数字和字符串可以是假的。

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'}); 

我真的不知道为什么你描述的情况不起作用。我想不出任何不合理的理由。但不相交的工会绝对有效。

+0

是的,但我不想修改数据(至少尚未)。 – dkl