How to combine object properties in typescript?

Typescript

Typescript Problem Overview


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?

Typescript Solutions


Solution 1 - Typescript

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); 

Solution 2 - Typescript

> 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

Solution 3 - Typescript

> (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

Solution 4 - Typescript

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};

Solution 5 - Typescript

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

Solution 6 - Typescript

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 }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionWawaBrotherView Question on Stackoverflow
Solution 1 - TypescriptAlkasaiView Answer on Stackoverflow
Solution 2 - TypescriptbasaratView Answer on Stackoverflow
Solution 3 - TypescriptHavView Answer on Stackoverflow
Solution 4 - TypescriptTrilok SinghView Answer on Stackoverflow
Solution 5 - TypescriptEugenioView Answer on Stackoverflow
Solution 6 - TypescriptByron BroughtenView Answer on Stackoverflow