Home > Enterprise >  Prevent overlapping properties when spreading multiple objects in a new one
Prevent overlapping properties when spreading multiple objects in a new one

Time:09-07

Let's say we have

x = {a:65, b:634, c:74};
y = {o:453, e:5342, g:543}
z = {o:453, e:5342, b:543}


// Doing this should be okay
const both = {...x, ...y}

// However, when doing this:
const both = {...x, ...z}

I need it to show some error like "Property b cannot be reassigned" or whatever, just don't let it compile. Any suggestions?

Edit: I know I can easily write a function to combine the objects and conditionally raise an exception but the point is that I need to do such kind of checking before runtime. It would be very helpful if it can be done using typescript, eslint or any trick that can check for such condition before runtime...

CodePudding user response:

The easiest way is to make a simple utility function..

You can get the keys of each, and use includes to make sure the key doesn't already exists in the other keys.

eg.

const x = {a:65, b:634, c:74};
const y = {o:453, e:5342, g:543};
const z = {o:453, e:5342, b:543};

function join(a,b) {
  const ak = Object.keys(a);
  const bk = Object.keys(b);
  for (const k of bk)
    if (ak.includes(k)) 
      throw new Error(`key ${k} cannot be re-assigned`);
  return {...a, ...b};
}

console.log(join(x, y));
console.log(join(x, z));

If you wish to do some checking at designtime using Typescript, one idea is to get the intersection types of the 2 objects, if the intersection is never, we could then make a fake type that returns true, or false if an overlap. If you then try and assign true to this type and there is an overlap you will get an error. The fake assignment on a good bundler should also remove this fake statement.

eg.

const x = {a:65, b:634, c:74};
const y = {o:453, e:5342, g:543};
const z = {o:453, e:5342, b:543};

type NoOverlap<A extends object, B extends object> = 
  keyof A & keyof B extends never ? true : false;

const _dummy1:NoOverlap<typeof x, typeof y> = true;
const _dummy2:NoOverlap<typeof x, typeof z> = true; //this will error.

TS Playground

CodePudding user response:

Here is a solution with n arguments:

function combineNoOverwrite(...args) {
  return args.reduce((acc, cur) => {
    for (var key in cur) {
      if (cur.hasOwnProperty(key) && !acc.hasOwnProperty(key)) {
        acc[key] = cur[key];
      } else {
        throw new Error(`key ${key} cannot be re-assigned`);
      }
    }
    return acc;
  });
}

CodePudding user response:

You can use the following.

function combine(x, y) {
    const array = Object.keys(x).concat(Object.keys(y))
    if (array.length != [...new Set(array)].length) {
        console.error("Error: Duplicate Key")
        return
    } 
    return {...x, ...y}
}
  • Related