2017-01-27 1 views
1

기본적으로 두 객체를 병합하는 일반 배열 축소 함수로 작업 할 입력을 얻으려고합니다. 다음 스 니펫은 실제 코드의 버려진 버전입니다. fl의 유형이 {}이고 IFoo & IBar이 아닌 이유는 무엇입니까?배열이있는 TypeScript 교차 유형 reduce

(나는이 특정 예는 쉽게 하나의 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에 할당해야합니다 유형을 설정 이 두 가지 제약 조건은 {}입니다. 따라서 유형 검사기는 U ~ {}을 유추합니다.

왜 반환 유형이 IFoo & IBar인지 알 수 없습니까? 형식 검사기는 코드의 런타임 동작에 대해 이유를 두지 않습니다. 즉, flatten의 매개 변수는 감소를 통해 다양한 유형을 취합니다. (IFoo | IBar)[] 유형의 배열은 IFooIBar을 모두 가질 수 있습니다 (단지 IFoo의 배열 일 수 있음). 이기종 목록을 과즙 형태로 채우는 것을 감안할 때 그 구성 형태를 상당히 정교하게 증명할 필요가 있으며 기계가 그러한 증거를 작성할 수 있다고 기대하는 것이 합리적이지 않은 것처럼 보입니다.

+0

끔찍한 답변! 자세한 설명을 정말 감사드립니다. – marvinhagemeister

관련 문제