Object destructuring for structuring a new object

637 views Asked by At

i have an object coming from an API respone, looks like this:

{
  // ...
  customerName: 'Jake',
  customerUserName: 'jak3',
  customerEmail: '[email protected]',
  // ...
}

and i want to declare a new object named apiUser to use in my app which sould look like this:

{
  name: 'Jake',
  userName: 'jak3',
  email: '[email protected]'
}

i know i can do that using Object.assign() like this:

let apiUser = {};
Object.assign(apiUser, {
  name: response.customerName || 'John Doe', // customerName may be an empty string
  userName : response.customerUserName,
  email: response.customerEmail
});

Finally the question is: Can i do that by object destructuring? I've already tried:

let apiUser = {};
{customerName: apiUser.name, customerUserName: apiUser.userName, customerEmail: apiUser.email} = response;

but throwed and SyntaxError: Unexpected token : Is there any right syntax or should i stick with Object.assign()? And please don't forget the "John Doe" condition.

4

There are 4 answers

0
BotNet On BEST ANSWER

It works as you'd expect:

let response = {
  // ...
  customerName: 'Jake',
  customerUserName: 'jak3',
  customerEmail: '[email protected]',
  // ...
};


// Destructuring Assignment (w/ default value)
let apiUser = {};
({ customerName:     apiUser.name = 'John Doe', //<-- default value with '='
   customerUserName: apiUser.userName, 
   customerEmail:    apiUser.email
 } = response );


// Assign Prototype Method
/*
let apiUser = {};
Object.assign(apiUser, {
  name: response.customerName || 'John Doe', // customerName may be an empty string
  userName : response.customerUserName,
  email: response.customerEmail
});
*/

console.log(apiUser);

According to the MDN documentation of Assignment without declaration:

The ( .. ) around the assignment statement is required syntax when using object literal destructuring assignment without a declaration.

{a, b} = {a: 1, b: 2} is not valid stand-alone syntax, as the {a, b} on the left-hand side is considered a block and not an object literal.

However, ({a, b} = {a: 1, b: 2}) is valid, as is var {a, b} = {a: 1, b: 2}

NOTE: Your ( ..) expression needs to be preceded by a semicolon or it may be used to execute a function on the previous line.


Note: both Object.Assign and destructured assignment are by-and-large not available in Internet Explorer (Edge is a different story). Take that into consideration for your implementation.

0
Joseph Ditton On

your final example is good you just need to wrap parens around the statement like this:

({customerName: apiUser.name, customerUserName: apiUser.userName, customerEmail: apiUser.email} = response)

however that wont let you do the conditional value. For that you would need to do Object.assign or one of the other methods you discussed.

EDIT

Turns out you can do the conditional value!

({customerName: apiUser.name = "John Doe", customerUserName: apiUser.userName, customerEmail: apiUser.email} = response)
2
Tobi Kremer On

Why not just assign to a new variable, getting rid of the up-front assignment with let and then modifying the variable:

const apiUser = {
  name: response.customerName || 'John Doe',
  userName : response.customerUserName,
  email: response.customerEmail
};

Or if you want to add to the already existing fields:

const apiUser = Object.assign({}, originalObject, {
  name: response.customerName || 'John Doe',
  userName : response.customerUserName,
  email: response.customerEmail
}

This should also work:

const { customerName: name, customerUserName: userName, customerEmail: email } = originalObject;
const apiUser = {
  name,
  userName,
  customerEmail
};
2
Richard Knop On

You could do something like:

let response = {
    CustomerName: '',
    CustomerUsername: 'jak3',
    CustomerEmail: '[email protected]',
};
let apiUser = {
    Name: '',
    Username: '',
    Email: '',
};

(
    [
        apiUser.Name,
        apiUser.Username,
        apiUser.Email
    ] = [
        response.CustomerName || 'John Doe',
        response.CustomerUsername,
        response.CustomerEmail
    ]
);
console.log(apiUser);

However I am not sure how is that an improvement in readability as compared to not using any fancy feature and instead just doing:

let response = {
    CustomerName: '',
    CustomerUsername: 'jak3',
    CustomerEmail: '[email protected]',
};
let apiUser = {
    Name: response.CustomerName || 'John Doe',
    Username: response.CustomerUsername,
    Email: response.CustomerEmail,
};
console.log(apiUser);

Surely this is easier to read and understand? Is there any specific reason why you are trying to use a more esoteric syntax to achieve this?