0

Can someone explain the method signature below:

export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;

This was the answer to a question about converting a union to an intersection type in ts: https://stackoverflow.com/a/50375286/457156

However I cannot follow the method signature.

Let's break it down:

Ternary operator as an argument

(U extends any ? (k: U) => void : never)

is this saying "if an object is provided, then the expected argument should be a function (k: U) => void

extends

(U extends any ? (k: U) => void : never) extends (k: infer I)

infer I presume infers the type of I The rest I am completely baffled by.

Any help would be appreciated. Here is a discussion thread that I didn't quite follow: https://github.com/Microsoft/TypeScript/issues/27907

Nick Mitchell
  • 1,207
  • 13
  • 24

1 Answers1

1

You already got the first part right, let's call that one T1:

export type T1<U> = (U extends any ? (k: U) => void : never);

So what we have left is (with parantheses for better readability):

export type UnionToIntersection<U> = (T1<U> extends (k: infer I) => void) ? I : never;

This one is again just a usage of the ternary operator with the condition T1<U> extends (k: infer I) => void. The infer keyword allows us to let typescript infer the type at this place to use it later in the type definition. So basically this part says:

"If T1 extends a function (k) => void, use the type of its parameter k, otherwise never."

So what the whole statement does (if U is not never) is, from U create a type (k: U) => void only to then infer the parameter k's type, which apparently gets inferred as a very specific type, resulting in the intersection of what Uis a union of.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Grochni
  • 1,663
  • 20
  • 25