Last active
July 5, 2024 06:26
-
-
Save zRains/9e68a35649af6de7463fd2d1d068c823 to your computer and use it in GitHub Desktop.
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 StrLen<T extends string, R extends Array<string> = []> = T extends `${infer C}${infer P}` | |
? StrLen<P, [...R, C]> | |
: R['length'] | |
type StrSplit<T extends string, S extends string, R extends Array<string> = []> = T extends `${infer X}${S}${infer Y}` | |
? StrSplit<Y, S, StrLen<X> extends 0 ? R : [...R, X]> | |
: StrLen<T> extends 0 | |
? R | |
: [...R, T] | |
type TailProp<T extends string> = T extends `${string}.${infer U}` ? TailProp<U> : T | |
type PickSource<T extends Array<string>, S extends Record<string, any> = {}> = { | |
[K in T[number] as TailProp<K>]: PickSourceDeep<K, S> | |
} | |
type ParseInt<T> = T extends `${infer N extends number}` ? N : never | |
type PickSourceDeep< | |
T extends string, | |
S extends Record<string, any> | Array<unknown> = {}, | |
__Sp extends Array<string> = StrSplit<T, '.'>, | |
__R = never, | |
> = __Sp extends [infer C, ...infer R] | |
? S extends Array<unknown> | |
? PickSourceDeep< | |
never, | |
NonNullable<Extract<S[ParseInt<C>], Array<unknown> | Record<string, any>>>, | |
R extends Array<string> ? R : [], | |
S[ParseInt<C>] | |
> | |
: C extends keyof S | |
? PickSourceDeep< | |
never, | |
NonNullable<S[C]> extends Record<string, any> ? NonNullable<S[C]> : never, | |
R extends Array<string> ? R : [], | |
S[C] | |
> | |
: unknown | |
: __R | |
function pickProps<T extends Record<string, any>, K extends Array<Extract<keyof T, string>> | Array<string>>( | |
source: T, | |
keys: K, | |
): Partial<PickSource<K, Required<T>>> { | |
const result: Partial<PickSource<K, Required<T>>> = Object.create(null) | |
keys.forEach((key) => { | |
if (typeof key === 'string') { | |
let keyPath = key.split('.') | |
Reflect.set( | |
result, | |
keyPath[keyPath.length - 1], | |
keyPath.reduce<unknown>((s, k) => (typeof s === 'undefined' ? s : Reflect.get(s!, k)), source), | |
) | |
} else { | |
Reflect.set(result, key, Reflect.get(source, key)) | |
} | |
}) | |
return result | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage: