It seems like the issue lies in the fact that your K
type is associated with an object that is not directly utilized; there is no direct passing of a value of type K
into the function combineObjects()
. The compiler's process of inferring generic type parameters goes through multiple phases, eventually resorting to fallback types like unknown
. While the specifics might be a bit fuzzy, essentially, the compiler tries to deduce the type K
based on the input values for the arguments a
and b
, which it accomplishes. However, it defers processing T1
and
T2</code until after this step, possibly causing the issue.</p>
<p>To resolve this, consider focusing on types that are more directly used. Since only the <em>keys</em> of your <code>K
type matter, you can redefine
K
to represent just those keys:
declare const combineObjects: <K extends string | number, T1, T2>(
a: Record<K, T1>,
b: Record<K, T2>
) => Record<K, T1 & T2>
const r = combineObjects(
{ a: { x: 123 }, b: { x: 456 } },
{ a: { y: "foo" }, b: { y: "bar" } }
);
r.a.x.toFixed(); // works fine
r.b.y.toUpperCase(); // alrighty
This configuration looks good. If the previous solution didn't work, the next step would have involved aligning the generic type parameters precisely with the a
and b
parameters:
declare const combineObjects: <A extends object, B extends Record<keyof A, any>>(
a: A,
b: B
) => Record<keyof A, A[keyof A] & B[keyof A]>;
const r = combineObjects(
{ a: { x: 123 }, b: { x: 456 } },
{ a: { y: "foo" }, b: { y: "bar" } }
);
r.a.x.toFixed(); // all good
r.b.y.toUpperCase(); // perfectly fine
which also resolves the issue.
Here is the link to view the code in the TypeScript Playground