0

A similar question has been asked, but I feel it doesn't fully answer my question.

If we have an array of objects of both unknown shape and of unknown length, is it possible to create an intersection of their types with TypeScript?

As an example, if we had a function that took objects and merged those objects into one.

function merge(objects: any[]) {
  return objects.reduce((acc = {}, o) => Object.assign(acc, o));
}

const mergedObject = merge([
  { foo: "something" },
  { foo: "something else" },
  { bar: 100 },
  { bar: 500, baz: false },
]);

How would we be able to make a return type for this function, keeping in mind that the function can be passed any number of objects with different properties?

I could foresee doing a limited version, with a set number of generic arguments like so:

function merge<A, B, C, D, E, F, G>(
  objects: [A, B?, C?, D?, E?, F?, G?]
): A & B & C & D & E & F & G {
  return objects.reduce((acc = {} as any, o) => Object.assign(acc, o)) as any;
}

Although this is pretty silly, it does however give us auto complete and type checking, but it would only work with up to a certain number of objects and seems like there should be a better way to do it.

Is there some way to type this nicely? Assuming of course the inputs to the function are static, as shown in the example.

Riho
  • 43
  • 6

1 Answers1

1

Is there some way to type this nicely

Nope. In fact here is the signature for Object.assign from the TypeScript sourcecode (it gives up after 4 parameters):

/**
 * Copy the values of all of the enumerable own properties from one or more source objects to a
 * target object. Returns the target object.
 * @param target The target object to copy to.
 * @param source The source object from which to copy properties.
 */
assign<T, U>(target: T, source: U): T & U;

/**
 * Copy the values of all of the enumerable own properties from one or more source objects to a
 * target object. Returns the target object.
 * @param target The target object to copy to.
 * @param source1 The first source object from which to copy properties.
 * @param source2 The second source object from which to copy properties.
 */
assign<T, U, V>(target: T, source1: U, source2: V): T & U & V;

/**
 * Copy the values of all of the enumerable own properties from one or more source objects to a
 * target object. Returns the target object.
 * @param target The target object to copy to.
 * @param source1 The first source object from which to copy properties.
 * @param source2 The second source object from which to copy properties.
 * @param source3 The third source object from which to copy properties.
 */
assign<T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;

/**
 * Copy the values of all of the enumerable own properties from one or more source objects to a
 * target object. Returns the target object.
 * @param target The target object to copy to.
 * @param sources One or more source objects from which to copy properties
 */
assign(target: object, ...sources: any[]): any;
basarat
  • 261,912
  • 58
  • 460
  • 511