1

I have a function which effectively merges objects together like so

function merge(...objects) {
  let temp = {};
  for(const obj of objects) {
    for(const key in obj) {
      temp[key] = obj[key];
    }
  }
  return temp;
}

What is the correct way to describe the output type such that if for example: objects is of type [{a: number}, {b: string}], the output is of type {a: number, b: string}?

My attempt at this intuitively is as follows:

type _return<T extends any[]> = {
  [name in keyof T]: typeof T[name]
};
function merge<T extends any[]>(...objects: T): _return<T> {
  let temp: _return<T> = {};
  for(const obj of objects) {
    for(const key in obj) {
      temp[key] = obj[key];
    }
  }
  return temp;
}

I know this is incorrect, but maybe it will serve as a better description of my intentions.

I've taken a look at how lodash types merge objects, and it seems even they have given up

Edit: Typos in code

Valerie Thiesent
  • 891
  • 1
  • 8
  • 17
  • 1
    Is [this](https://tsplay.dev/N7gkrN) what you're looking for? Please consider specifying multiple input/output combinations. You may be happy with an intersection of all input types (like `Object.assign()` gives you in TypeScript) or maybe you need a single object type, or maybe you care about overwriting properties (so `merge({a: 1}, {a: ""})` should result in `{a: string}` as opposed to `{a: never}`), etc., etc. There are lots of potential edge cases and rabbit holes one could go down, so I'm hoping you could head some of that off with a well-specified use case. Cheers! – jcalz Sep 09 '21 at 04:09
  • @jcalz my honest intention is to do exactly as this code does. allowing for overwriting, preferring the rightmost argument. I'm relatively new to typescript, though I've been working in javascript for some years, and this fiddle you have produced is far beyond my comprehension. It looks like it does what Im looking for, but if you could elaborate on, well, really any of it, I would _greatly_ appreciate it. – Valerie Thiesent Sep 09 '21 at 04:18
  • "Do exactly as this code does" is not specific enough. If I interpret that literally, the return type should correspond exactly to the set of possible values that come out of the function given an argument list of type `T`, but that would require an omniscient compiler and an arbitrarily expressive type system, neither of which are available at the moment. At the other extreme, we could say that the output type is `unknown` which is sound but woefully incomplete. Presumably you want something between those two extremes and it would be nice if you could give some use cases you care about. – jcalz Sep 09 '21 at 13:26
  • Yeah, actually, does [this question](https://stackoverflow.com/questions/49682569/typescript-merge-object-types) and its answer cover everything you care about? If not, please edit this question so as to distinguish it from the other one. – jcalz Sep 09 '21 at 13:32
  • 1
    Clearly, then, I'm not understanding your request for clarification. What information am I not communicating by describing that the original javascript snippet i have provided is as complex as the implementation i am working with gets? The code takes no edge cases into consideration. it is a shallow copy, overwriting keys when they conflict. I just dont know what additional information you are looking for. the linked question seems to do the trick. I think marking this as a duplicate would be fair (I wasnt able to find this question myself, likely from not know what this would be called.) – Valerie Thiesent Sep 09 '21 at 14:12
  • 1
    I guess the point is moot now, but I was asking for edge cases in how you *call* `merge()` and what you expect the output type to be. Look at [this code](https://tsplay.dev/N9JBqm) to see the happy case (where all properties are enumerable, known to the compiler, and non-generic, and where the tuple passed in is fixed-length) and a slew of sad cases. Some sad cases could be addressed and others are just unsolvable with TS today. And the right typing for `merge()` depends strongly on how you plan to use it. – jcalz Sep 09 '21 at 14:42
  • This makes more sense. These as you say, unhappy cases, I see how they could be problematic. Though none of them are things I need to support, as objects are vetted before beginning this merge process for validity, so I suppose all's well that ends well! Thanks for the help. – Valerie Thiesent Sep 09 '21 at 15:56

0 Answers0