Skip to content

couzic/immutable-lens

Repository files navigation

immutable-lens

Type-safe Lens API for immutable updates in deep data structures

Features

  • No mutations (obviously...)
  • Human-friendly API
  • Update your Redux store, your React component state, your Immutable.js collection... Whatever !
  • Bring in your favorite libraries (Ramda, lodash-fp, date-fns...)
  • Optimized for the strict equality checks performed in React.PureComponent, connect()...
  • Written in TypeScript, designed for maximal type-safety

Quickstart

Install

$ npm i -S immutable-lens

Create lens

import {createLens} from 'immutable-lens'

type State = {
   user: {
      name: string
      age: number
   }
}
const lens = createLens<State>()

Focus

const userLens = lens.focusPath('user')
const nameLens = userLens.focusPath('name')
const ageLens = lens.focusPath('user', 'age')

Read

const state: State = {
   user: {
      name: 'Bob',
      age: 18
   }
}

userLens.read(state) // {name: 'Bob', age: 18}
nameLens.read(state) // 'Bob'

Update

const setNameToJohn = 
   // THE FIVE LINES BELOW ARE ALL EQUIVALENT
   nameLens.setValue('John')
   nameLens.update(currentName => 'John')
   userLens.setFields({name: 'John'})
   userLens.updateFields({name: (currentName) => 'John'})
   userLens.updatePartial(user => ({name: 'John'}))

setNameToJohn(state) // {user: {name: 'John', age: 18}}

Compose updates with pipeUpdaters()

import {createLens, pipeUpdaters} from 'immutable-lens'

type State = {
   user: {
      name: string
   }
}

const state = {
   user: {
      name: 'Bob',
   }
}

const nameLens = createLens<State>().focusPath('user', 'name')

const setNameToJohn = nameLens.setValue('John')
const uppercaseName = nameLens.update(name => name.toUpperCase())

const setNameToJOHN = pipeUpdaters(
   setNameToJohn,
   uppercaseName
)

const updatedState = setNameToJOHN(state) // {user: {name: 'JOHN', age: 18}}

Use defaultTo() to avoid undefined values when reading or updating optional types

import {createLens} from 'immutable-lens'

type State = {
   loggedUser?: {
      name: string
      age: number
   }
}

const state = {
   // optional loggedUser field is undefined
}

const nameLens = createLens<State>()
   .focusOn('loggedUser')
   .defaultTo({name: 'Guest', age: 0})
   .focusOn('name')

const name = nameLens.read(state) // 'Guest'

const setNameToBob = nameLens.setValue('Bob')
const updatedState = setNameToBob(state) // {user: {name: 'Bob', age: 0}}

Focus on array index

import {Lens, createLens} from 'immutable-lens'

type Person = {
   name: string
}

type State = {
   friends: Person[] 
}

const firstFriendLens = createLens<State>()
   .focusOn('friends')
   .focusIndex(0)
   
const firstFriend: Person | undefined = firstFriendLens.read({friends: []})

Releases

No releases published

Packages

No packages published