gpt4 book ai didi

javascript - 如何用同一对象的属性替换占位符位置?

转载 作者:行者123 更新时间:2023-12-05 06:15:42 25 4
gpt4 key购买 nike

我正在使用 typescript 。也请包括支持 typescript 的答案。

以下是一个具有一些深层属性的对象。

const startObject = {
Hardware: {propertiesFromhardware: {}},
Software: {propertiesFromsoftware: {}},
Middleware: {propertiesFromDown: {}},
electronics: {hardware_c: "Hardware", otherProperty1: {hardware_e: "Hardware", otherSubProperty1: {}}, otherProperty2: {}},
tech_items: {software_d: "Software", otherProperty1: {otherSubProperty1: {middleware_r: "Middleware", }}},
gadgets:{hardware_t: "Hardware", software_d: "Software", otherProperty1: {otherSubProperty1: {middleware_r: "Middleware", }}},
}

无论你在哪里看到“硬件”、“软件”或“中间件”,它都应该被替换为来自以下对象的值——无论它们有多深。

因此最终结果将是:预期结果


// this is what we get when the startObject is transformed
// note that after removing all the occurences of "Hardware"/ "Software" / "Middleware"; these values will be removed so that final result looks like this. (with all placeholders replaced"

const finalObject = {
electronics: {hardware_c: {propertiesFromhardware: {}, otherproperties...}, otherProperty1: {hardware_e: {propertiesFromhardware: {}, otherproperties...}, otherSubProperty1: {}}, otherProperty2: {}},
tech_items: {software_d: {propertiesFromsoftware: {}, otherproperties...}, otherProperty1: {otherSubProperty1: {middleware_r: {propertiesFromDown: {}, otherproperties...}, }}},
gadgets:{hardware_t: {propertiesFromhardware: {}, otherproperties...}, software_d: {propertiesFromsoftware: {}, otherproperties...}, otherProperty1: {otherSubProperty1: {middleware_r: {propertiesFromDown: {}, otherproperties...}, }}},
}

请注意,这应该用相应的值替换所有深层出现的“硬件”、“软件”或“中间件”

最佳答案

为了让 TypeScript 有希望理解占位符替换,您需要确保 startObject 中的占位符。的属性是 string literal types而不仅仅是 string . TypeScript 的编译器倾向于将字符串文字扩展为 string除非它有一些暗示不要那样做。修改代码以便编译器记住 startObject 的最简单方法的文字字符串属性是使用 const assertion :

const startObject = { ... } as const;

这也将产生所有属性​​的效果 readonly ,这对您来说可能并不重要。


之后,我们需要在类型系统和运行时代码中表示占位符替换。类型系统替换代码如下所示:

type DeepReplace<T extends object, K extends keyof T> =
DeepReplaceInner<Omit<T, K>, Pick<T, K>> extends
infer O ? { [P in keyof O]: O[P] } : never

type DeepReplaceInner<T, U> = {
[K in keyof T]: (T[K] extends keyof U ? U[T[K]] : DeepReplaceInner<T[K], U>) extends
infer O ? { [K in keyof O]: O[K] } : never;
}

想法是DeepReplace<typeof startObject, "Hardware" | "Software" | "MiddleWare"将评估为 finalObject 的类型. DeepReplace的定义拆分传入的对象类型 T进入基础部分Omit<T, K>和替换零件 Pick<T, K> , 然后传入递归 DeepReplaceInner<T, U> .

DeepReplaceInner<T, U>遍历 T 的属性.如果任何值是 U 的键之一(替换),返回的属性来自U的相关值.否则返回 DeepReplaceInnerT 的属性(property).

那里有很多类型的杂耍,但这就是它的要点。


然后,运行时代码可能如下所示:

function deepReplace<T extends object, K extends keyof T>(
obj: T,
keys: K[]
): DeepReplace<T, K>;

function deepReplace(obj: any, keys: PropertyKey[]) {
const base: any = Object.assign({}, obj);
const repl: any = {};
for (const k of keys) {
repl[k] = base[k];
delete base[k];
}
function deepReplaceInner(base: any, repl: any) {
if (typeof obj !== "object" || obj === null) return obj;
const ret: any = {};
for (const k in base) {
ret[k] = (base[k] in repl) ? repl[base[k]] : deepReplaceInner(base[k], repl);
}
return ret;
}
return deepReplaceInner(base, repl);
}

我用过 overload将通用调用签名与 any 分开- 填充实现。该实现看起来很像类型签名的运行时版本:split obj进入baserepl基于 keys 中的键, 然后调用 deepReplaceInner(base, repl) ,它遍历了 base 的属性并替换作为 repl 键的任何属性使用来自 repl 的相应值, 否则向下递归。


让我们看看它是否有效:

const finalObject = deepReplace(startObject, ["Hardware", "Software", "Middleware"]);

您可以验证类型系统是否正常工作,因为 IntelliSense 知道存在以下叶属性:

finalObject.electronics.hardware_c.propertiesFromhardware;
finalObject.electronics.otherProperty1.hardware_e.propertiesFromhardware;
finalObject.electronics.otherProperty1.otherSubProperty1;
finalObject.gadgets.hardware_t.propertiesFromhardware;
finalObject.gadgets.otherProperty1.otherSubProperty1;
finalObject.gadgets.software_d.propertiesFromsoftware;

finalObject.tech_items.otherProperty1.otherSubProperty1.middleware_r.propertiesFromDown; finalObject.tech_items.software_d.propertiesFromsoftware;

您可以通过检查

的输出来验证运行时代码是否正常工作
console.log(JSON.stringify(finalObject));

我觉得两个都不错。


好的,希望对你有帮助;祝你好运!

参见 Playground link工作代码

关于javascript - 如何用同一对象的属性替换占位符位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62367309/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com