2016-11-29 2 views
2

ユニオンタイプのプロパティにアクセスするための慣習的な方法は、ユニオンでマージされたタイプの1つに欠けている可能性がありますか?次のエラーでユニオンタイプのプロパティにアクセスするための慣用的方法

type DataColumn = { 
    value: number; 
}; 

type CalculatedColumn = { 
    calculation: string; 
}; 

type Column = DataColumn | CalculatedColumn; 

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

フローtypecheck結果:

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

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

13: return c.value || c.calculation; 
         ^property `calculation`. Property not found in 
13: return c.value || c.calculation; 
         ^object type 

@dfkayeは "デフォルト" の場合のためにスローされたエラーがある場合は、それが動作することをTwitter上で指摘しました

誰かが説明できる:

  1. なぜ動作するのですか?それは意図的なものか副作用ですか?
  2. なぜ必要なのですか?列の型は常にvalueまたはcalculationのいずれかであるため、エラーは発生しません。
  3. より良い、より慣用的な方法がありますか?
  4. これは安全なアプローチですか、それとも将来的に破損する可能性がありますか?

PS:タイプアサーションを使用するタイプスクリプト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

関連する問題