Created
May 20, 2019 13:58
-
-
Save fvilante/97b8e61244ae1209088d3e2d4078d3ce to your computer and use it in GitHub Desktop.
Static Lenses prove of concept in Typescript
This file contains hidden or 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
// ======================================================================= | |
// Lenses | |
// ======================================================================= | |
type Setter<A, B extends keyof A> = Func2<A, A[B], A[B]> | |
type Getter<A, B extends keyof A> = Func<A, A[B]> | |
type Property<A, B extends keyof A> = B | |
type _Object<A> = A | |
type _NextType<A, B extends keyof A> = A[B] | |
interface LensState<A, B extends keyof A> { | |
_Object: _Object<A> // :: A | |
_NextObject: _NextType<A,B> // :: A[B] | |
Prop: Property<A,B> //:: B | |
Getter: Getter<A,B> // :: A -> A[B] | |
Setter: Setter<A,B> // :: A -> A[B] | |
} | |
class FirstPropSetter<A, B extends keyof A> { | |
constructor(private _State: LensState<A, B>) { } | |
// states | |
Prop = <K extends keyof A>(key: K): NextPropSetter<A, K> => | |
new NextPropSetter({ | |
_Object: this._State._Object, | |
_NextObject: this._State._Object[key], | |
Prop: key, | |
Getter: (_:A) => _[key], | |
Setter: (_:A, value: A[K]) => value | |
}) | |
} | |
class NextPropSetter<A, B extends keyof A> { | |
constructor(private _State: LensState<A, B>) { } | |
// states | |
NextProp = <K extends keyof A[B]>(key: K): NextPropSetter<A[B], K> => | |
new NextPropSetter({ | |
_Object: this._State._NextObject, | |
_NextObject: this._State._NextObject[key], | |
Prop: key, | |
Getter: undefined, | |
Setter: undefined, | |
}) | |
} | |
class Lens<A, B extends keyof A> { | |
// constructors | |
static Of = <T extends object>(o: T): FirstPropSetter<T, undefined> => | |
new FirstPropSetter({ | |
_Object: o, | |
_NextObject: undefined, | |
Prop: undefined, | |
Getter: undefined, | |
Setter: undefined, | |
}) | |
} | |
interface Test { | |
a: string | |
b: number | |
c?: { | |
x: number | |
y: number | |
z: { | |
a: number, | |
b: number | |
} | |
} | |
} | |
const test: Test = { | |
a:'2', | |
b: 3 | |
} | |
// Use (Static Lenses - from Above) | |
const L = (x: Test) => Lens.Of(x).Prop('c').NextProp('z').NextProp('a') | |
const L1 = (x: Test) => Lens.Of(x).Prop('a') | |
// Use (Dynamic Lenses - with pluck) | |
function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] { | |
return names.map(n => o[n]); | |
} | |
const zzz = pluck(test, ['a','b','a']) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment