2017-01-27 6 views
1

基本的に2つのオブジェクトをマージする汎用配列reduce関数で作業するための型を取得しようとしています。次のスニペットは、実際のコードのダンプされたバージョンです。 flのタイプが{}で、IFoo & IBarでないのはなぜですか?配列の縮小型の型交差の型

(私は、この特定の例では、簡単に単一Object.assign()の呼び出しに置き換えることができることを承知している。)

const flatten = <K, T>(prev: K, x: T): K & T => { 
    return Object.assign(prev, x); 
}; 

interface IFoo { 
    foo: true; 
} 

interface IBar { 
    bar: true; 
} 

const fooRes: IFoo = { foo: true }; 
const barRes: IBar = { bar: true }; 

const fl = [fooRes, barRes].reduce(flatten, {}); 

console.log(fl); // here, fl : {} 

答えて

3

The signature of reduce

reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U 

です(Tはの型パラメータであり、配列そのもの。)コードに直面しているので、

[fooRes, barRes].reduce(flatten, {}) 

タイプチェッカーの仕事は、Uが何であるか把握することです。のは、その推論を見てみましょう:

  1. fooRes : IFoobarRes : IBar、これにより[fooRes, barRes] : (IFoo | IBar)[]
  2. 、配列ですのでflattenIFoo | IBar
  3. flattenの戻り値の型(に設定されTパラメータで呼び出されているT ~ IFoo | IBar
  4. K & T)はK & (IFoo | IBar)
  5. です。flattenのそれは私たちに証拠の他のビットがそう{}
  6. U >= {}
  7. の最小の上限の型を持つinitialValueパラメータであるU >= (IFoo | IBar)
  8. に簡素化制約U >= (U & (IFoo | IBar))を与え、Uに割り当て可能でなければならないタイプを回しますこれらの2つの制約は{}です。したがって、型チェッカーはU ~ {}を推定します。

戻り値の型がIFoo & IBarであることがわからないのはなぜですか?型チェッカーは、コードの実行時の動作については理由がありません。つまり、flattenのパラメータは、削減を通じてさまざまな種類があります。 (IFoo | IBar)[]型の配列は、IFooIBarの両方を含むことは保証されていません。IFooの配列であってもかまいません。異種のリストを縮めてその構成型を縮小することは、かなり洗練された証明を必要とすることを控え、マシンがそのような証明を書くことができると期待するのは妥当ではないようです。

+0

驚くような答え!詳細な説明を本当に感謝します。 – marvinhagemeister

関連する問題