2017-02-15 15 views
4

私はこの状況にあり、意味のあるデータ構造の変更はできません。だから私はタグを追加することはできません。 タグなしのタイプを区別する方法はありますか?私はアヒルタイピングを試みましたが、うまくいきません。私exampleタグなしの結合されていないユニオン

type Result = Done | Error; // a disjoint union type with two cases 
type Done = { count: number } 
type Error = { message: string } 

const doSomethingWithDone = (obj: Done) => {/*...*/} 
const doSomethingWithError = (obj: Error) => {/*...*/} 

const f = (result: Result) => { 
    if (result.count) { 
    doSomethingWithDone(result) 
    } else { 
    doSomethingWithError(result) 
    } 
} 

エラーがある参照してください:それは互いに素組合がそうであるように

5: const doSomethingWithDone = (obj: Done) => {/*...*/} 
            ^property `count`. Property not found in 
10:  doSomethingWithDone(result) 
          ^object type 
6: const doSomethingWithError = (obj: Error) => {/*...*/} 
            ^property `message`. Property not found in 
12:  doSomethingWithError(result) 
          ^object type 

答えて

0

タイピングでは、Doneはカウントプロパティを持つことができないとは言わないので意味があります。

正確なオブジェクトタイプを使用すると、このexampleでわかるように、部分的に正しく機能しているように見えます。悲しいことに、あなたはまた、elseを明示的にチェックする必要があります。

By AugustinLF

+0

'count'が '0'または' message'では、 ' '''である場合であれば、このアプローチは失敗します。一見すると、私のタイプは、データの構造が変わったように見えるので、私の答えは下降していたと推測しています。しかし、オプションのフィールドを追加することは、あなたが記述したデータと互換性があります。このフォームでは、 '!== undefined'をチェックすることができます。 –

1

フローとしてエレガントなこの種のものをサポートしていません。ただし、正確なタイプが役立ちます。あなたの例の問題は、私は割り当てが私のオブジェクトリテラルを満たすためxインタフェース有効です

const x: Error = {message: 'foo', count: 'bar'}; 
f(x); 

を行うことができることです。だから、何かがErrorであれば、それはmessageのプロパティを持っていますが、あなたはそれが持っている他のプロパティについて何も知りません。そのため、countプロパティが存在することを確認しても、有効なオブジェクトタイプがDoneであることは証明されません。ここに助けることができる

正確なタイプ:

type Result = Done | Error; // a disjoint union type with two cases 
type Done = {| count: number |} 
type Error = {| message: string |} 

const doSomethingWithDone = (obj: Done) => {/*...*/} 
const doSomethingWithError = (obj: Error) => {/*...*/} 

const f = (result: Result) => { 
    if (result.count) { 
    doSomethingWithDone(result) 
    } else if (result.message) { 
    doSomethingWithError(result) 
    } 
} 

// Expected error. Since Error is an exact type, the count property is not allowed 
const x: Error = {message: 'foo', count: 'bar'}; 
f(x); 

tryflow link)正確な種類を作るに加えて、私はあなたのelseelse ifに変更しなければならなかったことを

注意。もちろん、厳密な型を使用すると、オブジェクトに無関係のフィールドを持たせることができないという欠点があります。しかし、私はそれがdisjoint unionを使うためにdiscriminatorフィールドを絶対に加えることができないなら、最良の選択だと思う。

関連する問題