object-standard-path
Version:
Safely get/set deep nested properties with standard path, strong type support
90 lines (88 loc) • 2.96 kB
JavaScript
var PathItemType;
(function (PathItemType) {
PathItemType[PathItemType["Object"] = 0] = "Object";
PathItemType[PathItemType["Array"] = 1] = "Array";
})(PathItemType || (PathItemType = {}));
var ARRAY_KEY_REG = /\[\d+\]/g;
var isObject = function (value) { return typeof value === 'object'; };
var isArray = function (value) { return Array.isArray(value); };
var deepClone = function (source) {
if (typeof source !== 'object') {
return source;
}
if (source instanceof Date) {
return new Date(source.getTime());
}
if (source instanceof Map) {
var mapClone_1 = new Map();
source.forEach(function (value, key) {
mapClone_1.set(deepClone(key), deepClone(value));
});
return mapClone_1;
}
if (source instanceof Set) {
var setClone_1 = new Set();
source.forEach(function (value) {
setClone_1.add(deepClone(value));
});
return setClone_1;
}
if (Array.isArray(source)) {
var arrayClone = source.map(function (item) { return deepClone(item); });
return arrayClone;
}
var objClone = {};
for (var key in source) {
if (source.hasOwnProperty(key)) {
objClone[key] = deepClone(source[key]);
}
}
return objClone;
};
var getPathItems = function (path) {
var pathItems = [];
path.split('.').forEach(function (path) {
var _a;
var objectKey = path.replace(ARRAY_KEY_REG, '');
pathItems.push({
type: PathItemType.Object,
key: objectKey,
});
(_a = path.match(ARRAY_KEY_REG)) === null || _a === void 0 ? void 0 : _a.forEach(function (arrayKey) {
pathItems.push({
type: PathItemType.Array,
key: arrayKey.replace(/\[|\]/g, ''),
});
});
});
return pathItems;
};
var pathGet = function (object, path) {
var value = object;
getPathItems(path).forEach(function (pathItem) {
value = isObject(value) || isArray(value) ? value[pathItem.key] : undefined;
});
return value;
};
var pathSet = function (object, path, value) {
var current = object;
var pathItems = getPathItems(path);
pathItems.forEach(function (pathItem, index) {
if (index === pathItems.length - 1) {
current[pathItem.key] = value;
}
else {
if (current[pathItem.key] === undefined) {
current[pathItem.key] =
pathItems[index + 1].type === PathItemType.Array ? [] : {};
}
current = current[pathItem.key];
}
});
};
var pathSetImmutable = function (object, path, value) {
var clonedObject = deepClone(object);
pathSet(clonedObject, path, value);
return clonedObject;
};
export { pathGet, pathSet, pathSetImmutable };