4 ms·
This fails on: const result = merge({ a: 1 }, { a: "fdsfsd" }) The correct type is quite complex and depends on whether or not `exactOptionalPropertyTypes`
by Benjamin_Dobell 4y ago
This fails on:
const result = merge({ a: 1 }, { a: "fdsfsd" })
The correct type is quite complex and depends on whether or not `exactOptionalPropertyTypes` is enabled.
EDIT: I think this is correct for when `exactOptionalPropertyTypes` is off.
type OptionalKeys<T extends { [key in symbol | string | number]?: unknown }> = { [K in keyof T]: {} extends Pick<T, K> ? K : never }[keyof T]
function merge<
A extends { [K in symbol | string | number]?: unknown },
B extends { [K in symbol | string | number]?: unknown },
>(a: A, b: B): {
[K in Exclude<keyof B, keyof A>]: B[K]
} & {
[K in Exclude<keyof A, keyof B>]: A[K]
} & {
[K in keyof A & keyof B]: K extends OptionalKeys<B> ? A[K] | Exclude<B[K], undefined> : B[K];
}
That's for when `exactOptionPropertyTypes` is enabled. With it disabled, then you'd replace `Exclude<B[K], undefined>` with `B[K]`.
As to whether this is a good idea. Ah... it's not :P
- KrishnaShripad 4y agoWow yeah it gets way too complex if you want to track the types of properties within the objects too! If that is the case, then I would just prefer to do this instead as it is much simpler: type Value = { a: string } const result = merge<Value, Value>({ a: 1 }, { a: "fdsfsd" })