An open API service indexing awesome lists of open source software.

https://github.com/couzic/immutable-lens

Type-safe Lens API for immutable updates in complex data structures
https://github.com/couzic/immutable-lens

equality-check functional-lenses immutable lens state-management typescript update

Last synced: 4 months ago
JSON representation

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

Awesome Lists containing this project

README

          

# 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
```sh
$ npm i -S immutable-lens
```

#### Create lens
```typescript
import {createLens} from 'immutable-lens'

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

#### Focus
```typescript
const userLens = lens.focusPath('user')
const nameLens = userLens.focusPath('name')
const ageLens = lens.focusPath('user', 'age')
```

#### Read
```typescript
const state: State = {
user: {
name: 'Bob',
age: 18
}
}

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

#### Update
```typescript
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()`
```typescript
import {createLens, pipeUpdaters} from 'immutable-lens'

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

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

const nameLens = createLens().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
```typescript
import {createLens} from 'immutable-lens'

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

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

const nameLens = createLens()
.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
```typescript
import {Lens, createLens} from 'immutable-lens'

type Person = {
name: string
}

type State = {
friends: Person[]
}

const firstFriendLens = createLens()
.focusOn('friends')
.focusIndex(0)

const firstFriend: Person | undefined = firstFriendLens.read({friends: []})
```