1
\$\begingroup\$

The original idea behind the problem is that the API I'm working with returns one type of a response for GET, and requires another type to do POST / PUT. The object I'm receiving from the GET has a format like this:

 const rawObject = {
  data1: {
    id: 1,
    value: 444
  },
  data2: null
 }

In order to be able to update it, or do a POST request to create a new one, I had to convert it into this format (This is the final output of my solution as well):

const convertedObject = {
  data1: 444,
  data2: null
};

The object I'm converting consists of another objects within it (One level max - as in the first example) or null. If the object is not null, I only care about the value of a nested object, therefore I flatten it as - data1: 444.

The solution I came up with is this (It works perfectly):

const rawObject = {
  data1: {
    id: 1,
    value: 444
  },
  data2: null
}

let convertedObject: any = {};

Object.entries(rawObject).map((item: any) => {
  const rawObjectKey = item[0];
  const rawObjectValue = item[1];
  if (rawObjectValue) {
    convertedObject = {...convertedObject, ...{[rawObjectKey]: rawObjectValue.value}};
    return;
  }
  convertedObject = {...convertedObject, ...{[rawObjectKey]: null}};
  return;
});
console.log(convertedObject); // Check the Output in example above

Stackblitz

I decided to use Object.entries() as I need both key:value pairs available. The if check I'm doing is there because object could have null value, therefore rawObjectValue would be null.

\$\endgroup\$
2
\$\begingroup\$

Review

  • Your final return statement is redundant.
  • The use of const is correct here (rawObjectKey, rawObjectValue) because you only assign these variables once. Many developers tend to use let or var here incorrectly.
  • Your method is a bit convoluted with those almost-equal code blocks. convertedObject = {...convertedObject, ...

Alternative

You could write this more compact, DRY and using built-in function reduce. We start with an empty object {} and inject each entry with the flattened data to obtain the result.

 const convertedObject = Object.entries(rawObject).reduce(
  (acc, item) => { 
    acc[item[0]] = item[1] != null ? item[1].value : null;
    return acc;
  }, {});

Future Releases

There is a thing called optional chaining aka null propagation aka the Elvis operator. It's not standard Typescript (yet?), but is already supported in babel-plugin-proposal-optional-chaining.

This is a feature request to track. If ever implemented, it would allow us to call something like item[1]?.value:null instead of item[1] != null ? item[1].value : null.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.