You want to distribute the Omit across a union. Luckily, you can use distributive conditional types to achieve this:
type DistributiveOmit<T, K extends keyof any> = T extends any
? Omit<T, K>
: never;
The T extends any construction looks like it doesn’t do much, but since T is a type parameter, it distributes the conditional type across any union constituents of T.
Let’s test it:
type CC = DistributiveOmit<C, "toRemove">;
// type CC = Pick<A, "key1" | "key2"> | Pick<B, "key1" | "key3">
You can verify that this is equivalent to the CC type you want.
Link to code