I did some tests on javascript object.
Here is type code in this tests.

interface Country {
    name: string;
}

interface Customer {
    name: string;
    country?: Country
};

Object Literal comparison

Example

const objLiteral = [
    {
        name: 'Toyota',
        country: {
            name: 'Japan'
        },
    },
    {
        name: 'Nissan',
        country: {
            name: 'Japan'
        },
    },
    {
        name: 'Ford',
        country: {
            name: 'USA'
        },
    },
]

Toyota and Nissan have same country Japan.
Compare this country objects.

console.log(objLiteral[0].country === objLiteral[1].country)
# => false

This is false because there are two country object in memory.

Manipulated object comparison

Example

const japan: Country = {
    name: 'Japan',
}

const usa: Country = {
    name: 'U.S.A'
}

const c1: Customer = {
    name: 'Toyota',
    country: japan
}

const c2: Customer = {
    name: 'Nissan',
    country: japan
}

const c3: Customer = {
    name: 'Ford',
    country: usa,
}

var customers: Customer[] = [];
customers.push(c1);
customers.push(c2);
customers.push(c3);

This is same object as example above.
Compare this country objects.

console.log(customers[0].country === customers[1].country)
# => true

This is true because it is pointing same country object.

Object merge

variable (const) name is used as key of merged object.

const country: Country = japan
const cs1: Customer = {
    name: 'Toyota',
    country
}

Using spread syntax, object key is used as ke of merged object.

const japanObj: { [key: string]: Country } = {
    country: japan
}

const cs2: Customer = {
    name: 'Nissan',
    ...japanObj
}

Compare these country objects.

console.log(cs1.country === cs2.country)
# => true

Recources

https://dev.to/girlie_mac/spread-syntax-three-dots-tricks-you-can-use-now-aob