Is there a way to create a generic function in TypeScript 4.4+ that is equivalent to {...a,...b} operation? Both a
and b
are records, but their types are unknown in advance. I want to define a generic type that enforces arbitrary functions to perform the {...a,...b} operation.
Here's an example that is not working as expected:
type Rec = Record<string, unknown>
type ExtendRec = <X extends Rec, Y extends X>(x: X) => Y
// or <X extends Rec, Y extends Rec>(x: X) => Y&X
const addA:ExtendRec = <X extends Rec>(x:X) => ({...x, a: 'a'})
const addB:ExtendRec = <X extends Rec>(x:X) => ({...x, b: 'b'})
const addC:ExtendRec = <X extends Rec>(x:X) => ({...x, c: 'c'})
const blank = {} // expected {}
const a = addA(blank) // expected {a:string}, actual:{}
const ab = addB(a) // expected {a:string,b:string}, actual:{}
const abc = addC(ab) // expected {a:string,b:string,c:string}, actual:{}
The error message on each of the addA, addB,addC functions is as follows:
Type '<X extends Rec>(x: X) => X & { c: string; }' is not assignable to type 'ExtendRec'.
Type 'X & { c: string; }' is not assignable to type 'Y'.
'X & { c: string; }' may be different from the subtype of constraint 'Record<string, unknown>'.
It's puzzling because if we remove the ExtendRec
function annotations, TypeScript can infer object assign operations correctly. However, it seems challenging to define a generic function type that restricts an arbitrary function to that specific extend operation.