object-standard-path
Version:
Safely get/set deep nested properties with standard path, strong type support
19 lines (16 loc) • 2.26 kB
TypeScript
type ExcludeEmptyPath<T> = Exclude<T, ''>;
type AvailableKey = string | number;
type UnaccessibleObjectType = Function | Map<any, any> | WeakMap<any, any> | Set<any> | WeakSet<any> | Date | RegExp | Error | Promise<any> | Symbol;
type AnyPath<T, P extends string> = 0 extends 1 & T ? P extends '' ? any : `${P}${any}` : never;
type ArrayPath<T, P extends string> = T extends Array<infer V> ? ExcludeEmptyPath<P> | Path<V, `${P}[${number}]`> : never;
type ObjectPath<T, P extends string> = T extends object ? T extends UnaccessibleObjectType ? never : keyof T extends infer K ? K extends keyof T & AvailableKey ? ExcludeEmptyPath<P> | `${Path<T[K], `${P extends '' ? K : `${P}.${K}`}`>}` : never : never : never;
type Path<T, P extends string = ''> = AnyPath<T, P> extends never ? ArrayPath<T, P> extends never ? ObjectPath<T, P> extends never ? P : ObjectPath<T, P> : ArrayPath<T, P> : AnyPath<T, P>;
type ArrayPathValueInner<T, K, R extends string> = K extends '' ? T extends Array<infer V> ? R extends '' ? V : PathValue<V, R> : any : K extends keyof T ? T[K] extends Array<infer V> ? R extends '' ? V : PathValue<V, R> : any : any;
type ArrayPathValue<T, P extends string> = P extends `${infer K}[${number}].${infer R}` ? R extends '' ? any : ArrayPathValueInner<T, K, R> : P extends `${infer K}[${number}]${infer R}` ? ArrayPathValueInner<T, K, R> : never;
type ObjectPathValueInner<T, K, R extends string = ''> = T extends UnaccessibleObjectType ? any : K extends keyof T ? R extends '' ? T[K] : PathValue<T[K], R> : any;
type ObjectPathValue<T, P> = P extends `${infer K}.${infer R}` ? R extends '' ? any : ObjectPathValueInner<T, K, R> : P extends `${infer K}` ? ObjectPathValueInner<T, K> : never;
type PathValue<T, P extends string = ''> = ArrayPathValue<T, P> extends never ? ObjectPathValue<T, P> extends never ? any : ObjectPathValue<T, P> : ArrayPathValue<T, P>;
declare const pathGet: <T, P extends Path<T, "">>(object: T, path: P) => PathValue<T, P>;
declare const pathSet: <T, P extends Path<T, "">>(object: T, path: P, value: PathValue<T, P>) => void;
declare const pathSetImmutable: <T, P extends Path<T, "">>(object: T, path: P, value: PathValue<T, P>) => T;
export { Path, PathValue, pathGet, pathSet, pathSetImmutable };