Skip to content

Instantly share code, notes, and snippets.

@smidhonza
Created October 26, 2020 13:49
Show Gist options
  • Save smidhonza/6311d0fb84746bdf8c9483a64e083d97 to your computer and use it in GitHub Desktop.
Save smidhonza/6311d0fb84746bdf8c9483a64e083d97 to your computer and use it in GitHub Desktop.
const has = <T extends object>(property: keyof T) => (obj: T) => !!obj[property];
const head: <T>(array: T[]) => T | undefined = (array) => array[0];
const prop = <T>(property: keyof T) => (object: T) => object[property];
const path = (bits: string[]) => (object: any): any => {
const [property, ...rest] = bits;
const value = prop(property)(object);
if (head(rest)) {
return path(rest)(value);
}
return value;
};
interface ILens {
get: (value: any) => any;
set: (key: any) => (value: any) => any;
}
const lens = (get: any) => (set: any): ILens => ({ get, set });
const view = <T>(lens: ILens) => (obj: T) => lens.get(obj);
const set = <T, V>(lens: ILens) => (value: V) => (object: T) => lens.set(value)(object);
const assoc = <V, T>(key: keyof T) => (value: V) => (object: T): T => ({ ...object, [key]: value });
const assocPath = <P extends string[], V, T>(path: P) => (value: V) => (obj: T): V => {
if (path.length === 0) {
return value;
}
const [head, ...tail] = path;
if (tail.length) {
const nextObj = has(head)(obj) ? obj[head] : {};
const nextValue = assocPath(tail)(value)(nextObj);
return assoc(head)(nextValue)(obj)
}
return assoc(head)(value)(obj);
};
const lensProp = (key: string) => lens(prop(key))(assoc(key));
const lensPath = (key: string[]) => lens(path(key))(assocPath(key));
describe('test', () => {
it('workz', () => {
const myLenSimple = lensProp('name');
expect(view(myLenSimple)({ name: 'Joe' })).toEqual('Joe')
expect(set(myLenSimple)('Carol')({ name: 'Joe' })).toEqual({ name: 'Carol' })
const myLens = lensPath(['a', 'b', 'c']);
expect(view(myLens)({ a: { b: { c: 40} }})).toEqual(40)
expect(set(myLens)('5')({ a: { b: { c: 40} }})).toEqual({a: {b: {c: '5'}}})
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment