From 049b5b351a88a18c3c6d9084411091f1125cb322 Mon Sep 17 00:00:00 2001 From: robonen Date: Tue, 20 May 2025 19:20:03 +0700 Subject: [PATCH] feat(core/stdlib): implement get function and remove getByPath --- core/stdlib/src/collections/get/index.ts | 34 ++++++++ .../stdlib/src/collections/getByPath/index.ts | 84 ------------------- core/stdlib/src/collections/index.ts | 2 +- 3 files changed, 35 insertions(+), 85 deletions(-) create mode 100644 core/stdlib/src/collections/get/index.ts delete mode 100644 core/stdlib/src/collections/getByPath/index.ts diff --git a/core/stdlib/src/collections/get/index.ts b/core/stdlib/src/collections/get/index.ts new file mode 100644 index 0000000..888c058 --- /dev/null +++ b/core/stdlib/src/collections/get/index.ts @@ -0,0 +1,34 @@ +import { type Collection, type Path } from '../../types'; + +export type ExtractFromObject, K> = + K extends keyof O + ? O[K] + : K extends keyof NonNullable + ? NonNullable[K] + : never; + +export type ExtractFromArray = + any[] extends A + ? A extends readonly (infer T)[] + ? T | undefined + : undefined + : K extends keyof A + ? A[K] + : undefined; + +export type ExtractFromCollection = + K extends [] + ? O + : K extends [infer Key, ...infer Rest] + ? O extends Record + ? ExtractFromCollection, Rest> + : O extends readonly any[] + ? ExtractFromCollection, Rest> + : never + : never; + +type Get = ExtractFromCollection>; + +export function get(obj: O, path: K) { + return path.split('.').reduce((acc, key) => (acc as any)?.[key], obj) as Get | undefined; +} \ No newline at end of file diff --git a/core/stdlib/src/collections/getByPath/index.ts b/core/stdlib/src/collections/getByPath/index.ts deleted file mode 100644 index 6ceea36..0000000 --- a/core/stdlib/src/collections/getByPath/index.ts +++ /dev/null @@ -1,84 +0,0 @@ -type Exist = T extends undefined | null ? never : T; - -type ExtractFromObject, K> = - K extends keyof O - ? O[K] - : K extends keyof Exist - ? Exist[K] - : never; - -type ExtractFromArray = any[] extends A - ? A extends readonly (infer T)[] - ? T | undefined - : undefined - : K extends keyof A - ? A[K] - : undefined; - -type GetWithArray = K extends [] - ? O - : K extends [infer Key, ...infer Rest] - ? O extends Record - ? GetWithArray, Rest> - : O extends readonly any[] - ? GetWithArray, Rest> - : never - : never; - -type Path = T extends `${infer Key}.${infer Rest}` - ? [Key, ...Path] - : T extends `${infer Key}` - ? [Key] - : []; - -// Type that generate a type of a value by a path; -// e.g. ['a', 'b', 'c'] => { a: { b: { c: PropertyKey } } } -// e.g. ['a', 'b', 'c', 'd'] => { a: { b: { c: { d: PropertyKey } } } } -// e.g. ['a'] => { a: PropertyKey } -// e.g. ['a', '0'], => { a: [PropertyKey] } -// e.g. ['a', '0', 'b'] => { a: [{ b: PropertyKey }] } -// e.g. ['a', '0', 'b', '0'] => { a: [{ b: [PropertyKey] }] } -// e/g/ ['0', 'a'] => [{ a: PropertyKey }] -// -// Input: ['a', 'b', 'c'], constrain: PropertyKey -// Output: { a: { b: { c: PropertyKey } } } - -export type UnionToIntersection = ( - Union extends unknown - ? (distributedUnion: Union) => void - : never -) extends ((mergedIntersection: infer Intersection) => void) - ? Intersection & Union - : never; - - -type PathToType = T extends [infer Head, ...infer Rest] - ? Head extends string - ? Head extends `${number}` - ? Rest extends string[] - ? PathToType[] - : never - : Rest extends string[] - ? { [K in Head & string]: PathToType } - : never - : never - : string; - -export type Generate = UnionToIntersection>>; -type Get = GetWithArray>; - -export function getByPath(obj: O, path: K): Get; -export function getByPath(obj: Record, path: string): unknown { - const keys = path.split('.'); - let currentObj = obj; - - for (const key of keys) { - const value = currentObj[key]; - - if (value === undefined || value === null) return undefined; - - currentObj = value as Record; - } - - return currentObj; -} diff --git a/core/stdlib/src/collections/index.ts b/core/stdlib/src/collections/index.ts index 64eab40..cab6a69 100644 --- a/core/stdlib/src/collections/index.ts +++ b/core/stdlib/src/collections/index.ts @@ -1 +1 @@ -export * from './getByPath'; \ No newline at end of file +export * from './get'; \ No newline at end of file