It was expained in the release notes when type inference from conditional types was introduced. Whether it will be a union or intersection depends on the variance of the inferred type. Intuitively, if a type is inferred as a common type for several values, it can be any of them (union), but if it's inferred as argument type for several functions, it must be acceptable by any of them (intersection).
Quote from the release notes:
The following example demonstrates how multiple candidates for the
same type variable in co-variant positions causes a union type to be
inferred:
type Foo<T> = T extends { a: infer U, b: infer U } ? U : never;
type T10 = Foo<{ a: string, b: string }>; // string
type T11 = Foo<{ a: string, b: number }>; // string | number
Likewise, multiple candidates for the same type variable in contra-variant positions causes an intersection type to be inferred:
type Bar<T> = T extends { a: (x: infer U) => void, b: (x: infer U) => void } ? U : never;
type T20 = Bar<{ a: (x: string) => void, b: (x: string) => void }>; // string
type T21 = Bar<{ a: (x: string) => void, b: (x: number) => void }>; // string & number
Further discussion can be found in the PR implementing this feature.
As a side note, it enables some cool tricks like union to intersection type conversion.