Created
September 27, 2019 14:43
-
-
Save bpander/6dd94fe4ac5184b5566c3a0f8a3597f1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import _get from 'lodash/get'; | |
import { setIn } from './objects'; | |
// This is a lens utility based off of https://github.com/utatti/lens.ts with 3 main differences. | |
// 1. It keeps track of the path from the source to the destination | |
// 2. It works by feeding that path into lodash's get/setWith functions | |
// 3. It doesn't use proxies (so IE is supported) | |
export type Setter<T> = (state: T) => T; | |
export interface Lens<T, U = T> { | |
k: <K extends keyof U>(key: K) => Lens<T, U[K]>; | |
get: (input: T) => U; | |
set: (setter: Setter<U>) => Setter<T>; | |
pipe: <V>(otherLens: Lens<U, V>) => Lens<T, V>; | |
path: (string | number)[]; | |
} | |
const makeLensFromPath = <T extends object, U>(path: (string | number)[]): Lens<T, U> => { | |
const get = (input: T) => (!path.length) ? input : _get(input, path); | |
return { | |
path, | |
get, | |
k: <K extends keyof U>(key: K) => makeLensFromPath<T, U[K]>([ ...path, key as (string | number) ]), | |
set: (setter: Setter<U>) => (input: T) => setIn(input, path, setter(get(input))), | |
pipe: <V>(lens: Lens<U, V>) => makeLensFromPath<T, V>([ ...path, ...lens.path ]), | |
}; | |
}; | |
export const makeLens = <TInput extends object>(): Lens<TInput> => makeLensFromPath([]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment