I would like to create the type definition for a function that takes two objects of different type but with common set of keys:
function myFunc(left, right, keys) {
// simplified:
for (const key of keys) {
console.log(key, left[key] === right[key])
}
return { left, right }
}
const left = {a: 1, b: 2}
const right = {b: 2, c: 3}
myFunc(left, right, ["b"])
This approach works, but changes the type of the returned right
which bites me in the code after the function call:
function myFunc<
Left,
Keys extends keyof Left
>(
left: Left,
right: Pick<Left, Keys>,
keys: Keys[],
): {
left: Left
right: Pick<Left, Keys>
} {
// ...
}
I want the returned type to be the same:
function myFunc<
Left,
Right extends Pick<Left, Keys>,
Keys extends keyof Left & keyof Right
>(
left: Left,
right: Right,
keys: Keys[]
): {
left: Left
right: Right
} {
// ...
}
However, now I get the complaint that the types Left[Keys]
and Right[Keys]
do not overlap. Which I don't fully get.
Any hints or ideas?
A weird solution but it seems to work in the simple example.
function myFunc<
L extends Pick<R, (keyof R & keyof L)>,
R extends Pick<L, (keyof R & keyof L)>,
K extends (keyof R & keyof L)>
(left: L, right: R, keys: K[]): { left: L, right: R }
{
for (const key of keys) {
console.log(key, left[key] === right[key])
}
return { left, right }
}
const left = { a: 1, b: 2, c: 4 };
const right = { b: 2, c: 3, d: 5 };
// Work:
myFunc(left, right, [ 'b' ]);
myFunc(left, right, [ 'b', 'c' ]);
// Error: Type '<>' is not assignable to type '"b" | "c"'.
myFunc(left, right, [ 'a' ]);
myFunc(left, right, [ 'd' ]);
myFunc(left, right, [ 'z' ]);
However it does seem to have some problems if the types of the values corresponding to the overlapping keys don't match. Might be a tricky way to fix it.
Overall it might just be best to turn off type checking for that one ===
line if possible.