export interface Lens { get(root: A): B set(root: A, newValue: B): A } export function prop(key: K): Lens { return { get: (root: A) => (root as any)[key], set: (root: A, newValue: any) => ({ ...root, [key]: newValue }), } } export function item(index: number): Lens { return { get: (root: I[]) => (root as any)[index], set: (nums: I[], newValue: I | undefined) => newValue === undefined ? [...nums.slice(0, index), ...nums.slice(index + 1)] : [...nums.slice(0, index), newValue, ...nums.slice(index + 1)], } } export function identityLens() { return { get: (root: A) => root, set: (root: A, newValue: any) => newValue, } }