Skip to content

Curried property accessor function that resolves deeply-nested object properties via dot/bracket-notation string path while mitigating TypeErrors via friendly and composable API.

License

Notifications You must be signed in to change notification settings

wilmoore/selectn.js

Repository files navigation

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.

Build Status Sauce Test Status Code Climate Greenkeeper badge JavaScript Style Guide types

yarn add selectn

or

npm install selectn --save

or

<script src="https://unpkg.com/selectn/selectn.min.js"></script>

You may also install selectn via Bower or jspm.

npm stats

npm NPM downloads David

browser support

The browsers listed in .zuul.yml are continuously tested; however, selectn is also known to work on older unlisted legacy browsers.

Build Status

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

npm

Features

  • Mitigate boilerplate guards like if (obj && obj.a && obj.a.b && obj.a.b.c).
  • Mitigate TypeError Cannot read property '...' of undefined.
  • Multiple levels of array nesting: 'group[0].section.a.seat[3]'.
  • Dashed key access: 'stats.temperature-today'.
  • When the value at the given path is a function, it is invoked and the functions returned value is returned.
  • selectn is auto-curried so partial application is automatic when you omit the second argument.
  • selectn uses Haskell style parameter order (AKA: data-last) which enables pointfree style programming.
  • Functions returned by selectn are higher-order property accessors which can be passed to other higher-order functions like map or filter.
  • Compatible with modern and legacy browsers, Node/CommonJS, and AMD.

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')
//=> [Function]

language.filter(spanish).length
//=> 2

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')
//=> [Function]

Promise.resolve(data).then(getId)
//=> 'd50afb80-a6be-11e2-9e96-0800200c9a66'

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]')
//=> [Function]

contacts.map(primaryAddress)
//=> [ '123 Main St, Broomfield, CO 80020', '123 Main St, Kirkland, IL 60146', undefined ]

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)
//=> 'd50afb80-a6be-11e2-9e96-0800200c9a66'

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)
//=> 'hi'

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:

Language Project
Python selectn

Related

Other JS packages whose friendly API is driven by selectn:

Inspiration

JS packages that have inspired selectn:

Alternatives

Alternative packages you might like instead of selectn:

Licenses

LICENSE

About

Curried property accessor function that resolves deeply-nested object properties via dot/bracket-notation string path while mitigating TypeErrors via friendly and composable API.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published