deep
🐡 Get, set, remove, and test for deeply nested properties
Helps you safely work with nested properties.
Install
Using Yarn:
$ yarn add @blakek/deep
…or using npm:
$ npm i --save @blakek/deep
Usage
import {
clone,
createGetter,
get,
has,
omit,
pluck,
remove,
set
} from '@blakek/deep';
const user = {
id: 'abf87de',
roles: ['alert:create', 'alert:read'],
sites: {
github: {
username: 'blakek'
}
}
};
const userCopy = clone(user);
user === userCopy;
user.id === userCopy.id;
user.roles === userCopy.roles;
user.roles[0] === userCopy.roles[0];
get('sites.github.username', user);
get('sites.facebook.username', user, 'no-account');
const getUsername = createGetter('sites.github.username');
getUsername(user);
has('sites.github', user);
omit(['roles', 'sites'], user);
pluck(['id', 'roles'], user);
remove('a', { a: 42, b: 123 });
set(123, 'a.b.c', { a: 42 });
API
For all these:
path
can be either a dot-notation string or array of path parts
clone
Returns a deep clone / deep copy of most values: primitive values, objects, arrays, Map, Set, Date, etc.
function clone<T extends unknown>(value: T): T;
const object = { value: 'yep' };
const cloned = clone(object);
cloned === object;
cloned.value === object.value;
get
/ createGetter
Gets the value for a given path with an optional fallback value.
function get(path: Path, object: object, fallbackValue?: any): unknown;
function createGetter(
path: Path,
fallbackValue?: any
): (object: object) => unknown;
const user = {
id: 'abf87de',
roles: ['alert:create', 'alert:read'],
sites: {
github: {
username: 'blakek'
}
}
};
get('id', user);
get('roles.0', user);
get('roles[0]', user);
get(['roles', 1], user);
get('sites.github.username', user);
get('sites.github.avatar.src', user, 'default.png');
const getID = get('id');
getID(user);
const getRoles = createGetter('roles');
getRoles(user);
has
/ createHas
Returns true
if a value was found at the given path or false
if nothing was
found.
function has(path: Path, object: any): boolean;
function createHas(path: Path): (object: any) => boolean;
const product = {
id: 'abf87de',
name: 'Logo T-Shirt',
attributes: {
isCool: undefined,
materials: ['cotton']
}
};
has('attributes.materials', product);
has(['avability', 'sizes'], product);
has('attributes.isCool', product);
const hasMaterials = createHas('attributes.materials');
hasMaterials(product);
get('attributes.isCool', product, false);
omit
/ createOmit
Returns a clone of an object with a list of properties removed.
Note: omit()
returns a clone with properties removed. If you'd rather modify
the existing object for performance, consider using remove()
.
function omit(properties: Path[], object: any): any;
function createOmit(properties: Path[]): (object: any) => any;
const user = {
username: 'blakek',
roles: ['alert:create', 'alert:read'],
sites: {
github: {
username: 'blakek'
}
}
};
omit(['roles', 'sites'], user);
omit(['username', 'roles', 'sites.doesnt.exist'], user);
const omitExtra = createOmit(['roles, sites']);
omitExtra(user);
pluck
/ createPluck
Gets a subset of properties from an object.
function pluck(properties: Path[], object: any): any;
const user = {
username: 'blakek',
roles: ['alert:create', 'alert:read'],
sites: {
github: {
username: 'blakek'
}
}
};
pluck(['username'], user);
pluck(['username', 'roles'], user);
const permissionInfo = pluck(['roles', 'username']);
permissionInfo(user);
remove
/ createRemove
Removes a value at a path and returns the object.
Note: remove()
modifies the passed-in object rather than creating a copy. If
you'd rather return a new object:
- use
omit()
; omit()
returns a clone with a list of properties removed - use
clone()
before remove()
- consider another solution (unchanged is really good)
function remove(path: Path, object: any): any;
function createRemove(path: Path): (object: any) => any;
const user = {
username: 'blakek',
password: 'wouldntyouliketoknow'
};
remove('password', user);
remove('property.does.not.exist', user);
const removePassword = createRemove('password');
removePassword({ username: 'bob', password: 'laskjfl' });
set
/ createSetter
Sets a value at a path and returns the object.
Note: set()
modifies the passed-in object rather than creating a copy. If
you'd rather return a new object:
- use
clone()
before set()
- consider another solution (unchanged is really good)
function set(value: any, path: Path, object: any): any;
function createSetter(path: Path, object: any): (value: any) => any;
const user = {
profile: {
bgColor: '#639'
}
};
set('tomato', 'profile.bgColor', user);
set('/images/user.png', 'profile.bgImage', user);
const logout = set(null, 'profile');
logout(user);
const setUsername = createSetter('username', user);
setUsername('blakek');
Contributing
Node.js and Yarn are required to work with this project.
To install all dependencies, run:
yarn
Useful Commands
| |
---|
yarn build | Builds the project to ./dist |
yarn format | Format the source following the Prettier styles |
yarn test | Run project tests |
yarn test --watch | Run project tests, watching for file changes |
License
MIT