WawaBrother
WawaBrother

Reputation: 2405

How to combine object properties in typescript?

I'd like to know the best way to do this, say I have two objects

var objectA = {
    propertyA: 1,
    propertyB: 2
    ...
    propertyM: 13
}

var objectB = {
    propertyN: 14,
    propertyO: 15
    ...
    propertyZ: 26
}

If objectC is created by

var objectC = Object.assign(objectA, objectB);

How can I declare/describe objectC, so the compiler/IDE knows that it has the properties of both objectA and objectB?

I'd like to find a way without the need of defining interfaces for objectA and objectB. I don't want to write declaration and definition/evaluation for the same property twice. This redundancy is significant if I have too many properties on an object.

(Is there an operator that can extract the interface/type of an existing object?)

Is it possible?

Upvotes: 158

Views: 220398

Answers (7)

Surya R Praveen
Surya R Praveen

Reputation: 3745

var apparel = [{
    "ctaText": "Apparel BTN",
    "formBlurb": "<ul><li>Apparel tracking and allergen management</li><li>Expiration tracking for waste reduction</li><li>Collaborative forecasting and versatile supply chain management</li></ul>",
    "formImage": "",
    "formHeading": "Fill out this form for apparel information.",
    "marketoFormId": "2902",
    "showModalSide": false,
    "viewModalBackground": "dark",
    "formImageTopPosition": "",
    "successSubmissionCta": "Apparel Submit",
    "successSubmissionMessage": "Thank you for choosing Apparel"
  }];

  var food = [{
      "ctaText": "Food BTN",
      "formBlurb": "<h4>Test blurb</h4><u>underline this text</u><ul><li>fashion</li><li>textiles</li><li>upholstery</li></ul>",
      "formImage": "https://images.net/card-food-erp-for-quality-harvest-foods.jpg",
      "formHeading": "Fill out this form for food information.",
      "marketoFormId": "1086",
      "showModalSide": true
    }];


    if (
      Object.keys(apparel).length !=
      Object.keys(food).length
    ) {
      const initialDataFound = {...apparel, ...food };
      console.log(this.initialDataFound);
    }

Final result concates both apparel and food objects

Upvotes: 0

Eugenio
Eugenio

Reputation: 623

Use Typescript spread operator it transpile to Javascript Object.assign()

If you need deep tree object merging you could use changing function of best-global package

Upvotes: 7

Byron Broughten
Byron Broughten

Reputation: 371

Lodash has an "extend" function that combines objects and lets Typescirpt know that the new object has the type you'd expect.

const a = { one: 1, two: 2 };
const b = { three: 3, four: 4 };
const c = lodash.extend(a, b);
// c: { one: 1, two: 2, three: 3, four: 4 }

Upvotes: 4

Trilok Singh
Trilok Singh

Reputation: 1363

try this..

const person = { name: 'TRilok', gender: 'Male' };
const tools = { computer: 'Mac', editor: 'Atom' };
const attributes = { handsomeness: 'Extreme', hair: 'Brown', eyes: 'Blue' };

const summary = {...person, ...tools, ...attributes};

Upvotes: 15

alkasai
alkasai

Reputation: 4033

Seems like this should do the trick:

var objectA = {
    propertyA: 1,
    propertyB: 2,
    .
    . // more properties here
    .
    propertyM: 13
};

var objectB = {
    propertyN: 14,
    propertyO: 15,
    .
    . // more properties here
    .
    propertyZ: 26
};

var objectC = {...objectA, ...objectB}; // this is the answer

var a = objectC.propertyA;

var n = objectC.propertyN;

Based on this article: https://blog.mariusschulz.com/2016/12/23/typescript-2-1-object-rest-and-spread


In addition, the order of the variables in the decomposition matters. Consider the following:

var objectA = {
    propertyA: 1,
    propertyB: 2, // same property exists in objectB
    propertyC: 3
};

var objectB = {
    propertyX: 'a',
    propertyB: 'b', // same property exists in objectA
    propertyZ: 'c'
};

// objectB will override existing properties, with the same name,
// from the decomposition of objectA
var objectC = {...objectA, ...objectB}; 

// result: 'b'
console.log(objectC.propertyB); 

// objectA will override existing properties, with the same name,
// from the decomposition of objectB
var objectD = {...objectB, ...objectA}; 

// result: '2'
console.log(objectD.propertyB); 

Upvotes: 292

Hav
Hav

Reputation: 938

(Is there an operator that can extract the interface/type of an existing object? Is it possible?)

You should go for typeof.

type typeA = typeof objectA;
type typeB = typeof objectB;

To get them merged you can use intersection operation as basarat already pointed out.

type typeC = typeA & typeB

Upvotes: 19

basarat
basarat

Reputation: 276235

so the compiler/IDE knows that it has the properties of both objectA and objectB?

Use an intersection type + generics. E.g. from here

/**
 * Quick and dirty shallow extend
 */
export function extend<A>(a: A): A;
export function extend<A, B>(a: A, b: B): A & B;
export function extend<A, B, C>(a: A, b: B, c: C): A & B & C;
export function extend<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;
export function extend(...args: any[]): any {
    const newObj = {};
    for (const obj of args) {
        for (const key in obj) {
            //copy all the fields
            newObj[key] = obj[key];
        }
    }
    return newObj;
};

More

Both are mentioned here : https://basarat.gitbooks.io/typescript/content/docs/types/type-system.html

Upvotes: 12

Related Questions