Created
March 18, 2017 01:44
-
-
Save typoerr/8bb28363e18c6690bbbb7bc169b9c7ec to your computer and use it in GitHub Desktop.
immtable-updater
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
/* API */ | |
export function getIn(src: object, path: _.Path) { | |
return _.parsePath(path).reduce((acc, k) => (acc as any)[k], src); | |
} | |
export function hasIn(src: object, path: _.Path) { | |
return _.existy(getIn(src, path)); | |
} | |
export function setIn(src: object, path: _.Path, value: object) { | |
return _.rec(src, _.parsePath(path), value, 0); | |
} | |
export function updateIn(src: object, path: _.Path, updater: Function) { | |
return _.rec(src, _.parsePath(path), updater, 0); | |
} | |
export function deleteIn(src: object, path: _.Path) { | |
path = _.parsePath(path); | |
return updateIn(src, path.slice(0, -1), (o: any) => { | |
const target = path[path.length - 1]; | |
return Array.isArray(o) ? o.filter((_, i) => i !== Number(target)) : _.omit(o, target); | |
}); | |
} | |
/* utils */ | |
export namespace _ { | |
export type Path = string | (string | number)[]; | |
export const isArray = Array.isArray; | |
export function isPlainObject(obj: object) { | |
return obj instanceof Object && Object.getPrototypeOf(obj) === Object.prototype; | |
}; | |
export function omit(src: any, key: string | number) { | |
const clone = { ...src }; | |
delete clone[key]; | |
return clone; | |
} | |
// 参考: https://github.com/debitoor/dot-prop-immutable | |
export function rec(src: any, path: _.Path, value: any, idx: number) { | |
let clone; | |
let key = path[idx]; | |
if (path.length > idx) { | |
if (Array.isArray(src)) { | |
clone = src.slice(); | |
} else { | |
clone = { ...src }; | |
} | |
clone[key] = rec(clone[key] !== undefined ? clone[key] : {}, path, value, idx + 1); | |
return clone; | |
} | |
return (typeof value === 'function') ? value(src) : value; | |
}; | |
export function parsePath(path: Path) { | |
return (typeof path === 'string') ? path.split('.') : [...path]; | |
} | |
export function existy(v: any) { | |
return !(v === null || v === undefined); | |
} | |
// export namespace walk { | |
// export interface Walker { | |
// (info: Info): void; | |
// } | |
// export interface Info { | |
// key: string | number; | |
// value: any; | |
// current: any; | |
// index: number; | |
// } | |
// } | |
// export function walk(src: object, path: Path, walker: walk.Walker) { | |
// const len = path.length; | |
// let index = -1; | |
// let current: any = src; | |
// while (++index < len) { | |
// const key = path[index]; | |
// const value = current ? current[key] : undefined; | |
// walker({ key, value, current, index }); | |
// if (isPlainObject(value) || isArray(value)) { | |
// current = value; | |
// } else { | |
// current = undefined; | |
// } | |
// } | |
// } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment