[英]Cast object nested properties to new type
I previously made a general purpose function that recursively cast nested property values into number:我之前做了一个通用的 function 递归地将嵌套属性值转换为数字:
type CastToNumber<T> = T extends string ? number : {
[K in keyof T]: CastToNumber<T[K]>
};
type StringMap = { [key: string]: any };
const castObjectValuesToNumber = function<T extends StringMap, K extends keyof T>(initialObj: T, nestedProp?: string): CastToNumber<T> {
let _castedObj: StringMap = {};
for(const [property, value] of Object.entries(initialObj)) {
if(typeof(value) === "object") {
const newVal = castObjectValuesToNumber(value, property) as CastToNumber<T>;
_castedObj = { ..._castedObj, ...newVal };
} else {
if(nestedProp) {
if(!_castedObj[nestedProp]) _castedObj[nestedProp] = {};
_castedObj[nestedProp][property] = +value;
} else {
_castedObj[property] = +value;
}
}
}
return _castedObj as CastToNumber<T[K]>;
}
This was working well for most objects but I recently had to cast this object and it didn't work.这对大多数对象都很有效,但我最近不得不投射这个 object 并且它不起作用。
const army = {
cavalry: {
light: { quantity: "0", health: "0" },
heavy: { quantity: "0", health: "0" }
},
infantry: {
light: { quantity: "0", health: "0" },
heavy: { quantity: "0", health: "0" }
},
magic: {
light: { quantity: "0", health: "0" },
heavy: { quantity: "30", health: "0" }
},
range: {
light: { quantity: "0", health: "0" },
heavy: { quantity: "0", health: "0" }
}
};
const result = castObjectValuesToNumber(army);
/*
result = {
light: { quantity: 0, health: 0 },
heavy: { quantity: 0, health: 0 }
};
wanted = {
cavalry: {
light: { quantity: 0, health: 0 },
heavy: { quantity: 0, health: 0 }
},
infantry: {
light: { quantity: 0, health: 0 },
heavy: { quantity: 0, health: 0 }
},
magic: {
light: { quantity: 0, health: 0 },
heavy: { quantity: 30, health: 0 }
},
range: {
light: { quantity: 0, health: 0 },
heavy: { quantity: 0, health: 0 }
}
}
*/
It is only returning a limited scope of nested properties, because it doesn't properly store properties and recursively set them.它只返回有限的 scope 嵌套属性,因为它没有正确存储属性并递归设置它们。 I can't find a way to make this function work for deeply nested properties.我找不到让这个 function 适用于深度嵌套属性的方法。
_castedObj = { ..._castedObj, ...newVal };
should be应该
_castedObj[property] = newVal;
it is a simple recursive function to iterate an object.它是一个简单的递归 function 来迭代 object。
const army = {cavalry:{light:{quantity:"0",health:"0"},heavy:{quantity:"0",health:"0"}},infantry:{light:{quantity:"0",health:"0"},heavy:{quantity:"0",health:"0"}},magic:{light:{quantity:"0",health:"0"},heavy:{quantity:"30",health:"0"}},range:{light:{quantity:"0",health:"0"},heavy:{quantity:"0",health:"0"}}}; function iterate(obj) { Object.keys(obj).forEach(function(key) { var value = obj[key]; if (typeof value === 'object' && value;= null) { iterate(value) } if (typeof value === "string") { obj[key] = +value. } }) } iterate(army) console.log(army)
.as-console-wrapper {max-height: 100% !important}
Here's a simple version, which recursively maps a function over an object/array/other structure:这是一个简单的版本,它递归地将 function 映射到对象/数组/其他结构上:
const deepMap = (fn) => (o) => Array.isArray (o)? o.map (deepMap (fn)): Object (o) === o? Object.fromEntries (Object.entries (o).map (([k, v]) => [k, deepMap (fn) (v)])): fn (o) const army = {cavalry: {light: {quantity: "0", health: "0"}, heavy: {quantity: "0", health: "0"}}, infantry: {light: {quantity: "0", health: "0"}, heavy: {quantity: "0", health: "0"}}, magic: {light: {quantity: "0", health: "0"}, heavy: {quantity: "30", health: "0"}}, range: {light: {quantity: "0", health: "0"}, heavy: {quantity: "0", health: "0"}}} console.log (deepMap (Number) (army))
.as-console-wrapper {max-height: 100%;important: top: 0}
Here we call it with the Number
constructor, but we could map using anything.这里我们用Number
构造函数调用它,但我们可以使用任何东西 map。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.