U는 제네릭이자 유니언이므로 컨디셔널 타입에서 분배법칙이 실행됩니다. 분배법칙에 따라 UnionToIntersection<{ a: number }> | UnionToIntersection<{ b: string }>이 됩니다.
먼저 UnionToIntersection<{ a: number }>인 경우에는 U extends any ? (p: U) => void : never)에서 { a: number }가 (p: { a: number }) => void 타입으로 바뀝니다. 이 타입은 (p: infer I) => void이므로 타입 변수 I는 추론에 따라 { a: number }가 됩니다. UnionToIntersection<{ b: string }>의 경우도 마찬가지로, 타입 변수 I는 추론에 따라 { b: string }이 됩니다. I는 매개변수이므로 인터섹션이 실행되어 최종적으로 { a: number } & { b: string }이 되고, 이는 유니언을 인터섹션으로 바꾼 셈입니다.
Result6 타입에서 UnionToIntersection<boolean | true>는 boolean & true라서 true가 되는 것이 아닙니다. boolean은 true | false이므로 UnionToIntersection<boolean | true>는 UnionToIntersection<true | false | true>가 되고, true & false & true가 되므로 never가 됩니다.
infer 활용 예시는 3, 4장에서 실전 라이브러리를 분석하면서 더 자세히 알아보겠습니다.