Skip to content

Instantly share code, notes, and snippets.

@jctaoo
Last active September 1, 2021 04:50
Show Gist options
  • Save jctaoo/f2bcd828d801c8d89e992efa6aafd8eb to your computer and use it in GitHub Desktop.
Save jctaoo/f2bcd828d801c8d89e992efa6aafd8eb to your computer and use it in GitHub Desktop.
多级 key 的获取与赋值
type Dot = ".";
type PopFirst<K extends string> = K extends `${infer A}${Dot}${infer B}`
? B
: K;
type PickFirst<K extends string> = K extends `${infer A}${Dot}${infer B}`
? A
: K;
type Check<
R,
K extends string
> = R extends Record<string, any>
? PickFirst<K> extends keyof R
? Check<R[PickFirst<K>], PopFirst<K>>
: undefined
: R;
function getValue<R extends Record<string, any>, K extends string>(
obj: R, key: K
): Check<R, K> {
if (key === "") {
console.error("Invalid key, the key can not be a empty string");
// @ts-ignore
return;
}
if (!key.includes(".") && Object.prototype.hasOwnProperty.call(obj, key)) {
return obj[key];
}
const levels = key.split(".");
let cur = obj;
for (const level of levels) {
if (Object.prototype.hasOwnProperty.call(cur, level)) {
cur = cur[level];
} else {
// @ts-ignore
return;
}
}
return cur as Check<R, K>;
}
type AssignObj = Record<string | number, any>;
function setValue<Value>(obj: AssignObj, key: string, value: Value): void {
if (key === "") {
console.error("Invalid key, the key can not be a empty string");
return;
}
if (!key.includes(".")) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
console.warn(`The key ${key} looks like already exists on obj.`);
}
obj[key] = value;
}
const levels = key.split(".");
const lastKey = levels.pop()!;
let cur = obj;
for (const level of levels) {
if (Object.prototype.hasOwnProperty.call(cur, level)) {
cur = cur[level] as AssignObj;
} else {
console.error(
`Cannot set value because the key ${key} is not exists on obj.`
);
return;
}
}
if (typeof cur !== "object") {
console.error(
`Invalid key ${key} because the value of this key is not a object.`
);
return;
}
if (Object.prototype.hasOwnProperty.call(cur, lastKey)) {
console.warn(`The key ${key} looks like already exists on obj.`);
}
cur[lastKey] = value;
}
let obj = { a: { b: "Hello", c: { D: "Hello World", E: 123 } } };
const value = getValue(obj, "a.c.E");
console.log(value);
setValue(obj, "a.d", 1234);
console.log(obj);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment