Explain Codes LogoExplain Codes Logo

How to get a subset of a JavaScript object's properties

javascript
functions
callbacks
promises
Anton ShumikhinbyAnton Shumikhin·Nov 13, 2024
TLDR

To quickly obtain a subset of an object's properties, use the destructuring syntax with the rest operator:

// Be quick and efficient in picking a and c, just like how my cat is fast at spotting the red laser. const { a, c, ...rest } = { a: 1, b: 2, c: 3, d: 4 }; const subset = { a, c }; // subset now proudly holds { a: 1, c: 3 }

In a more dynamic case, a reducer function can come in handy:

// It picks things better than you pick clothes for a date. const pick = (obj, keys) => keys.reduce((acc, key) => (key in obj && (acc[key] = obj[key]), acc), {});

Comprehensive solutions for your daily needs

Destructuring assignment in IIFEs

An Immediately Invoked Function Expression (IIFE) provides an alternative way of creating a subset:

// You'll want this on speed-dial, trust me. const subset = (({ a, c }) => ({ a, c }))({ a: 1, b: 2, c: 3, d: 4 });

Utility libraries — The all-rounder Lodash

Why reinvent the wheel when Lodash already gives you a wheel, and a spare one.

// Lodash, helping lazy developers since 2012. const _ = require('lodash'); const subset = _.pick(obj, ['a', 'c']);

The deadly duo: Spread and Object.entries

The spread syntax and Object.entries can tag team for an elegant solution:

// Nice and easy, like sunday morning. const obj = { a: 1, b: 2, c: 3, d: 4 }; const desiredKeys = new Set(['a', 'c']); const subset = Object.fromEntries( Object.entries(obj).filter(([key]) => desiredKeys.has(key)) );

Transform, roll out!

Ever feel like not only picking properties but also transforming them? There's a trick just for that.

Mapping entries like a pro

Object.entries, Object.fromEntries and map, make transformation as easy as ABC:

// Try saying that 10 times fast! const original = { a: 1, b: 2, c: 3 }; const transform = ([key, value]) => [key, value * 2]; const subset = Object.fromEntries( Object.entries(original).filter(([key]) => ['a', 'c'].includes(key)).map(transform) );

Strolling away from vendor dependencies

Say no more to vendor lock-in, with native JavaScript we can break these chains:

// Where's my locksmith? const subset = Object.keys(obj).reduce((acc, key) => { if (desiredKeys.has(key)) acc[key] = obj[key]; return acc; }, {});

Pearls from the deep — complex scenarios

Facing special property keys or nested objects? Don't sweat! We got your back.

Special keys, special handling

If your properties have symbols or non-standard keys, they need special attention, like my cat when it sees a cucumber:

// This ain't your standard baseball, is it? const specialKey = Symbol('special'); const obj = { a: 1, [specialKey]: 2 }; const subset = pick(obj, ['a', specialKey]); // Don't forget to let your function handle symbol keys!

Digging into nested objects

Nested objects are like those Russian nesting dolls, there's always something within:

// We are going Inception now. function pickNested(obj, keys) { return keys.reduce((acc, key) => { if (typeof obj[key] === 'object' && obj[key] !== null) { acc[key] = pickNested(obj[key], Object.keys(obj[key])); } else if (key in obj) { acc[key] = obj[key]; } return acc; }, {}); }

Best friend TypeScript

If you're a TypeScript aficionado, ensure your property picking isn't just typesafe, but also type-awesome:

// Type homecoming! function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> { return keys.reduce((accumulator, key) => { if (key in obj) { accumulator[key] = obj[key]; } return accumulator; }, {} as Pick<T, K>); }