playing around with TS 3.7.2 I found a bizzarre edge case and now I'm curious of knowing more about how type inference in a function works in this specific case.
interface A {
functions: { t: number, a: { test: number }; };
}
interface B {
functions: { t: number, b: { ciao: number }; };
}
function combineStuff<TNamespace extends {}>(stuff: { functions: Partial<TNamespace> }[]): TNamespace {
// Implementation irrelevant for the question
return {functions: merge({}, ...stuff.map(s => s.functions))} as any;
}
const a: A = { functions: { t: 1, a: { test: 1 } } };
const b: B = {functions: { t: 1, b: { ciao: 2 } }};
const c = combineStuff([a, b]);
c.a.test;
c.b.ciao; // Error. Why is that?
const d = combineStuff<A['functions'] & B['functions']>([a, b]);
d.a.test;
d.b.ciao; // Works well
My expectation was that both c.b.ciao
and d.b.ciao
were type safe, but accessing c.b.ciao
causes an error.
From this simple example seems that the generic type could be automatically inferred from the elements of the array, this hypothesis is also supported by the fact that in the call combineStuff<A['functions'] & B['functions']>([a, b]);
the TS compiler verifies that the types of a
and b
are actually correct.
Additionally the type inference works correctly for the first element of the array a
, I can type-safely access to c.a.test
.
Why do I need to explicitly supply the generic type to combineStuff()
to obtain the correct result? Why is inference on the first element of the array working correctly?