morphmorph icon indicating copy to clipboard operation
morphmorph copied to clipboard

:scream: Isomorphic transformations. Map, transform, filter, and morph your objects

Morph Morph

Isomorphic transformations. Map, transform, filter, reduce, and morph your objects

tested with jest linted with XO styled with prettier

Getting Started

$ npm i --save morphmorph

and then

const Mapper = require('morphmorph')

const mapper = new Mapper(/* [config] */)

const old = {
  here: {
    there: {
      anywhere: 'Earth'

const mappings = [ 'here.there.anywhere:location' ]

const transformation =, old)
// -> { location: 'Earth' }

Creating Transformations

Every transformation can be represented by a mapping passed in as the first parameter to Mappings can either be of type String or Object. A mapping such as 'before:after' is equivalent to: { field: 'before:after' }


const mappings = [
  '', // deeply nested target
  'data.user.updated:updated'      // deeply nested source
return, obj)


When creating a mapping, if you pass a function as the type parameter, the function you passed will be called with the following properties to produce the result:

const mapping = {
  field: 'name',
  type: function (value, mapping, options, sourceObj, targetObj) {
    // value: the value grabbed from the source object
    // mapping: this specific mapping
    // options: config you specified by `new Mapper(options)`
    // sourceObj: object you passed as, sourceObj)
    // targetObj: object you passed as, sourceObj, targetObj). Default to `{}`


You can also pass an Array of functions and MapLib will perform a right-to-left function composition:

const mapping = {
  field: 'id:pin',
  type: [
    Number,                   // called last
    v => v.substr(0, 4)
    v => v.replace(/\D/g, '') // called first
}[mapping], { id: 'U1234342'}) // -> 1234

Function Compositions

If you want to do function compositions the traditional way, you can use Mapper.compose(...myFilterFunctions). Again it will be a right-to-left composition.


By specifying your field property as an array, you can reduce multiple values into a single one. The values will be included as the first parameter of your type function. The target field is specified by the last mapping in your array

const response = {
  user: {
    firstName: 'Mike',
    lastName: 'Fix',
    professionInfo: {
      title: 'Mr',
      occupation: 'Software Engineer'

const mapping = {
  field: [
  type: ([name1, name2, title, occ]) =>
    `${title}. ${name1} ${name2} is a ${occ}`
}[mapping], response).description // -> 'Mr. Mike Fix is a Software Engineer'


You can specify a type system by passing in the types option:

const types = {
  number: Number,
  notNullString: v => (v || '')

const mapper = new Mapper({ types })

and then specify which type to use as a string for each mapping:

const mappings = [
  { field: 'haircolor', type: 'notNullString' },
  { field: 'daysRemaining': type: 'number' }

return, hairSubscriptionResponse)

Note: each function in the type specification is passed the same parameters as the normal type functions


You can pass in a config object to Mapper to create your own mapping system:

Field Type Default
types Object {}
objDelimiter String "."
mapDelimiter String ":"
preFilters Array []
postFilters Array []
const mapper = new Mapper({
  objDelimiter: '|',
  mapDelimiter: '->',
  types: { bool: Boolean },
  preFilters: [ FILTER_NULL ],
  postFilters: [ REMOVE_PASSWORD ]
  // add other fields to your config here

Static methods


Method used to grab a deeply nested field from an object.

const get = Mapper.get('key'/*, delimiter */)
const field = get({ key: true })
// -> true

Method used to apply a deeply nested field to an object.

const set = Mapper.assign(''/*, delimiter */)
const targetObject = set({}, 1)
// -> { user: { id: 1 } }

Method used to apply function compositions

const fun1 = v => `${v}!`
const fun2 = v => v.toUpperCase()
const fun3 = String

const exclaim = Mapper.compose(fun1, fun2, fun3)
exclaim('hey') // -> HEY!


Dependencies: None!
Size: <2KB gzipped


See /examples or test/index.spec.js for many examples of how to use MorphMorph.