Last active
September 1, 2021 04:50
-
-
Save jctaoo/f2bcd828d801c8d89e992efa6aafd8eb to your computer and use it in GitHub Desktop.
多级 key 的获取与赋值
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
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