-
Notifications
You must be signed in to change notification settings - Fork 7
/
lens.ts
54 lines (43 loc) · 1.56 KB
/
lens.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// Copyright (c) 2020 Jozty. All rights reserved. MIT license.
import type { PH } from './utils/types.ts';
import curryN from './utils/curry_n.ts';
// @types
type LensF_2<T, F> = (setter: LensSetter<T, F>) => Lens<T, F>;
type LensF_1<T, F> = (getter: LensGetter<T, F>) => Lens<T, F>;
type LensF =
& (<T, F>(getter: LensGetter<T, F>) => LensF_2<T, F>)
& (<T, F>(getter: PH, setter: LensSetter<T, F>) => LensF_1<T, F>)
& (<T, F>(getter: LensGetter<T, F>, setter: LensSetter<T, F>) => Lens<T, F>);
export type LensGetter<T, F> = (target: T) => F;
export type LensSetter<T, F> = (focus: F, target: T) => T;
export type GetTransformer<T, F, R> = (
focus: F,
) => LensTransformer<T, F, R>;
export type LensTransformer<T, F, R> = {
value: F;
transform: (
setter: LensSetter<T, F>,
target: T,
) => LensTransformer<never, R, never>;
};
export type Lens<T, F> = <R>(
getTransformer: GetTransformer<T, F, R>,
) => (target: T) => LensTransformer<never, R, never>;
function _lens<T, F>(
getter: LensGetter<T, F>,
setter: LensSetter<T, F>,
): Lens<T, F> {
return function <R>(getTransformer: GetTransformer<T, F, R>) {
return function (target: T) {
const focusedObj = getter(target);
const transformer = getTransformer(focusedObj);
return transformer.transform(setter, target);
};
};
}
/**
* Returns a lens for the given getter and setter functions. The `getter` "gets"
* the value of the focus; the setter "sets" the value of the focus. The `setter`
* should not mutate the data structure.
*/
export const lens = curryN(2, _lens) as LensF;