selectn
Curried property accessor function that resolves deeply-nested object properties via dot/bracket-notation string path while mitigating TypeErrors
via friendly and composable API.
npm install selectn --save
or
<script src="https://unpkg.com/selectn/selectn.min.js"></script>
You may also install selectn
via Bower, Duo, or jspm.
npm stats
browser support
The following browsers are continuously tested; however, selectn
is also supported and known to work on even older browsers not listed below:
Overview
allows you to refactor this:
person && person.info && person.info.name && person.info.name.full
into:
selectn('info.name.full', person)
or refactor this:
contacts.map(function (contact) {
return contact && contact.addresses && contact.addresses[0]
})
into:
contacts.map(selectn('addresses[0]')))
Demo
Features
- Mitigates boilerplate guards like
if (obj && obj.a && obj.a.b && obj.a.b.c) { return obj.a.b.c; }
. - Mitigates TypeError
Cannot read property '...' of undefined
. - Supports multiple levels of array nesting (i.e.
group[0].section.a.seat[3]
). - Supports dashed key access (i.e.
stats.temperature-today
). - If value at path is a function, the value returned is the return value of invoking the function.
- Partial application is automatic when you omit the second argument (i.e.
selectn
is curried). - Property accessor generated by
selectn
can be passed to higher-order functions like map or filter. - Compatible with modern and legacy browsers, Node/CommonJS, and AMD.
- Haskell style parameter order allows for pointfree style programming.
Non-Features
- No eval or Function (see:
eval
in disguise). - No typeof since, typeof is not a real solution to this problem but can appear to be due to the way the global scope is implied.
Usage example(s)
property accessor as predicate
Avoid annoying Cannot read property '...' of undefined TypeError
without writing boilerplate anonymous functions or guards.
var selectn = require('selectn')
var language = [
{ strings: { en: { name: 'english' } }},
{ strings: { es: { name: 'spanish' } }},
{ strings: { km: { name: 'khmer' } }},
{ strings: { es: { name: 'spanish' } }},
{ nodatas: {}}
]
var spanish = selectn('strings.es')
language.filter(spanish).length
point-free property accessor
Access deeply nested properties (including dashed properties) using point-free style.
var selectn = require('selectn')
var data = {
client: {
message: { 'message-id': 'd50afb80-a6be-11e2-9e96-0800200c9a66' }
}
}
var getId = selectn('client.message.message-id')
Promise.resolve(data).then(getId)
property accessor for functor
Avoid wrapping property accessors in anonymous functions.
var selectn = require('selectn')
var contacts = [
{ addresses: [ '123 Main St, Broomfield, CO 80020', '123 Main St, Denver, CO 80202' ] },
{ addresses: [ '123 Main St, Kirkland, IL 60146' ] },
{ phones: [] },
]
var primaryAddress = selectn('addresses[0]')
contacts.map(primaryAddress)
support for keys containing .
Pass an array as path instead of a string.
var selectn = require('selectn')
var data = {
client: {
'message.id': 'd50afb80-a6be-11e2-9e96-0800200c9a66'
}
}
selectn(['client', 'message.id'], data)
value at path is a function
Avoid var fn = data.may.be.a.fn; if (typeof fn === 'function') fn()
.
var selectn = require('selectn')
function hi () { return 'hi' }
var data = { may: { be: { a: { fn: hi } } } }
selectn('may.be.a.fn', data)
API (partial application)
selectn(String|Array)
arguments
path (String|Array)
Dot/bracket-notation string path or array.
returns
(Function)
Unary function accepting the object to access.
API (full application)
selectn(String|Array, Object)
arguments
path (String|Array)
Dot/bracket-notation string path or array.object (String|Array)
Object to access.
returns
(*|undefined)
Value at path if path exists or undefined
if path does not exist.
Other Languages
selectn
has inspired ports to other languages:
Related
Other JS packages whose friendly API is driven by selectn
:
Inspiration
JS packages that have inpsired selectn
:
Alternatives
Alternative packages you might like instead of selectn
:
Licenses