Created
June 20, 2022 09:25
-
-
Save sladg/c17c0c6628ad670b56d34095a061a270 to your computer and use it in GitHub Desktop.
Safely pick nested properties from object using dot-path.
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 GetIndexedField<T, K> = K extends keyof T | |
? T[K] | |
: K extends `${number}` | |
? '0' extends keyof T | |
? undefined | |
: number extends keyof T | |
? T[number] | |
: undefined | |
: undefined; | |
type FieldWithPossiblyUndefined<T, Key> = | |
| GetFieldType<Exclude<T, undefined>, Key> | |
| Extract<T, undefined>; | |
type IndexedFieldWithPossiblyUndefined<T, Key> = | |
| GetIndexedField<Exclude<T, undefined>, Key> | |
| Extract<T, undefined>; | |
export type GetFieldType<T, P> = P extends `${infer Left}.${infer Right}` | |
? Left extends keyof T | |
? FieldWithPossiblyUndefined<T[Left], Right> | |
: Left extends `${infer FieldKey}[${infer IndexKey}]` | |
? FieldKey extends keyof T | |
? FieldWithPossiblyUndefined<IndexedFieldWithPossiblyUndefined<T[FieldKey], IndexKey>, Right> | |
: undefined | |
: undefined | |
: P extends keyof T | |
? T[P] | |
: P extends `${infer FieldKey}[${infer IndexKey}]` | |
? FieldKey extends keyof T | |
? IndexedFieldWithPossiblyUndefined<T[FieldKey], IndexKey> | |
: undefined | |
: undefined; | |
export function _get<TData, TPath extends string, TDefault = GetFieldType<TData, TPath>>( | |
data: TData, | |
path: TPath, | |
defaultValue?: TDefault, | |
): GetFieldType<TData, TPath> | TDefault { | |
const value = path | |
.split(/[.[\]]/) | |
.filter(Boolean) | |
.reduce<GetFieldType<TData, TPath>>((value, key) => (value as any)?.[key], data as any); | |
return value !== undefined ? value : (defaultValue as TDefault); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment