0
const {name, slug, description, parent} = cat;
const saneCat = {name, slug, description, parent};

In the first expression, we define four constants by destructuring a messy object. In the second expression, we combine them into a new object. I would like to do this in a single step without duplicating the list of interesting fields, but because the first expression doesn't define an object, this seems to be impossible. Is it really? We are so close to a Clojurian win!

I have tried the following without success. Any ECMAScript compiler is fair game, but I don't have the option of just using Clojurescript.

const saneCat = {name, slug, description, parent} = cat; // name is not defined
const {...saneCat} = {name, slug, description} = cat;  // name is not defined
const saneCat = ({name, slug, description, parent} = cat); // name is not defined
const saneCat = ({name, slug, description, parent}) = cat; // name is not defined
const saneCat = {{name, slug, description, parent}} = cat; // unexpected token
const saneCat = {{name, slug, description, parent}} = {cat}; // unexpected token
Dan Ross
  • 3,396
  • 2
  • 28
  • 53
  • 1
    Why not use an existing library like `_.pluck(cat, ['name', 'slug', 'description', 'parent'])`? Destructuring is primarily for extracting properties into assignable expressions/variables. – loganfsmyth Aug 19 '15 at 18:02
  • You mean `_.pick`? I haven't used that before, thanks for pointing it out. It does solve my example. I was kind of hoping that ES6 comprehensions and destructuring together would be more flexible and concise than a library could be, but it doesn't look like those two language features were designed to be used together. – Dan Ross Aug 19 '15 at 18:23
  • Yeah woops, `_.pick(cat, ['name', 'slug', 'description', 'parent'])`. I actually noticed I typoed it and apparently forgot to fix it? :P You can *technically* use destructuring, but only in a way that is no shorter that your current example, e.g. `const saneCat = {}; ({name: saneCat.name, slug: saneCat.slug} = cat);` but wow is it unreadable – loganfsmyth Aug 19 '15 at 18:36
  • @Bergi Yes, it's a dup, but why point to another question which is itself a dup? –  Aug 19 '15 at 19:29

2 Answers2

2

Unfortunately, destructuring in ES6 is limited to assignments and parameter lists. There is a discussion of a "pick" operator which would do what you want, but don't hold your breath.

Meanwhile, the closest you can come is the following, which requires duplicating the list of properties:

const saneCat = 
  (({name, slug, description, parent}) => 
    ({name, slug, description, parent})
  )(cat);

Using the proposed pick syntax, you would be able write

const saneCat = {name, slug, description, parent} # cat;

Something like that should show up in ES29. Until then, you can use pick utilities of the sort mentioned in the comment, but personally, I hate writing properties as strings.

See also One-liner to take some properties from object in ES 6.

Community
  • 1
  • 1
1

Destructuring basically desugars as

({a} = obj}
// a = obj.a

({a: foo} = obj)
// foo = obj.a

({a: foo.bar} = obj)
// foo.bar = obj.a

so the only way to pull a key out of obj and put it into another object is to repeat the name of the key in both because there is no concise form for it, so to answer your question, you can technically do

const saneCat = {};
({
    name: saneCat.name,
    slug: saneCat.slug,
    description: saneCat.description,
    parent: saneCat.parent
} = cat);

but that is super hard to read and even harder to understand. I'd absolutely recommend using an existing library or function to do this, like Lodash's pick:

const saneCat = _.pick(cat, ['name', 'slug', 'description', 'parent'])
loganfsmyth
  • 135,356
  • 25
  • 296
  • 231