Issue
I would like to implement DeepIntersection
type that does following:
type Input =
| { message: string | number; type: "a"; a: number }
| { message: string | boolean; type: "b"; b: number };
type DeepIntersection<T> = /* TO IMPLEMENT */ T;
type Output = DeepIntersection<Input>;
// => { message: string; type: never; a: never; b: never };
// which then can be easly converted to => { message: string }
I know how to produce these:
// With Pick<T, keyof T>
type AlmostThereOutput1 = { message: string | number | boolean; type: "a" | "b" };
// With https://stackoverflow.com/a/47375979/11545965 but '&' instead of '|'
type AlmostThereOutput2 =
| { message: string | number; type: "a" }
| { message: string | boolean; type: "b" };
but unfortunatly I ran out of ideas how to produce what I actually want.
Context
Let's say that we have an array of objects of various types (possibly a discrimination union), and we want to implement a function that can update any item by it. This function could accept:
- callback
(prevItem: Item) => Item
(react useState style) - data
commonProps: Partial<DeepIntersection<Item>>
that can be safely injected into any existing item as such{...prevItem, ...commonProps}
.
EDIT - Additional explanation:
I called it DeepIntersection
because intersection operator &
works like this for non-object types:
type Intersection = 'a' & ('b' | 'a');
// => 'a'
This is exactly the behavior that I need but applied deeper for every property.
So in my example it would be:
type Message = (string | number) & (string | boolean); // string
type Type = "a" & "b"; // never
type A = number & undefined; // never
type B = undefined & number; // never
Result with never
s is perfectly fine too:
type Result = { message: string; type: never; a: never; b: never };
since removing never
properties is quite easy.
Currently I didn't think about a recursive solution, but if it's possible to implement I'd love to see both. I think about using this helper to possibly solve this: TypeScript allows unsafe Partial usage in generic