let's say we have these types
type Email = {id: number, type: "Email", email: string}
type Phone = {id: number, type: "Phone", phone: string}
type ContactInfo= Email | Phone
and we want to send it to an API or save it do database but the API accepts something like this
interface ContactInfoToSave {
id: number;
type: "Email" | "Phone";
phone?: string;
email?: string;
}
if we use UnionToIntersection
we get never
cause the type
cannot be merged to one it's like when you want to intersect UnionToIntersection<string | number>
it cannot be done.
I have a solution for it
type DistributiveOmit<T, K extends keyof T> = T extends any ? Omit<T, K> : never;
export type TaggedUnionToIntersection<T> = UnionToIntersection<
Partial<DistributiveOmit<T, keyof T>> & Pick<T, keyof T>
>;
Let me explain how does it work.
The default Omit
and Pick
utility type does not go inside each union type, but it's going to pick only the common type that available in every union type. also keyof
works exactly like that only will export the keys is common in each union;
so
type K = keyof ContactInfo; // the only common between Email and Phone is => "type" | "id"
now if we pick these two keys
type Picked = Pick<ContactInfo, keyof ContactInfo>; // {type: "Email" | "Phone", id: number}
Now we want to omit id
and type
but we want to go inside each union, so we can remove it. for this we can use Distributive conditional types hence the DistributiveOmit
.
After that we got something like
type Example = {id: number, type: "Email" | "Phone"} & ({phone?: string} | {email?: string})
now with UnionToIntersection
we can merge all of this together and make the ContactInfoToSave
I did not pull request because I thought let's discuss it a little about it.
like if the TaggedUnionToIntersection
is a good name or if we want to no common between union be Partial
or not.
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too