UNPKG

@frui.ts/helpers

Version:
40 lines (39 loc) 3.57 kB
export type BrowserNativeObject = Date | FileList | File; export type Primitive = null | undefined | string | number | boolean | symbol | bigint; export type IsAny<T> = 0 extends 1 & T ? true : false; export type IsNever<T> = [T] extends [never] ? true : false; export type PathString = string; export type Traversable = object; export type IsTuple<T extends ReadonlyArray<any>> = number extends T["length"] ? false : true; export type ArrayKey = number; export type Key = string; export type AsKey<T> = Extract<T, Key>; export type ToKey<T> = T extends ArrayKey ? `${T}` : AsKey<T>; export type PathTuple = Key[]; export type AsPathTuple<T> = Extract<T, PathTuple>; export type UnionToIntersection<U> = (U extends any ? (_: U) => any : never) extends (_: infer I) => any ? I : never; type AppendNonBlankKey<PT extends PathTuple, K extends Key> = K extends "" ? PT : [...PT, K]; type SplitPathStringImpl<PS extends PathString, PT extends PathTuple> = PS extends `${infer K}.${infer R}` ? SplitPathStringImpl<R, AppendNonBlankKey<PT, K>> : AppendNonBlankKey<PT, PS>; export type SplitPathString<PS extends PathString> = SplitPathStringImpl<PS, []>; type JoinPathTupleImpl<PT extends PathTuple, PS extends PathString> = PT extends [infer K, ...infer R] ? JoinPathTupleImpl<AsPathTuple<R>, `${PS}.${AsKey<K>}`> : PS; export type JoinPathTuple<PT extends PathTuple> = PT extends [infer K, ...infer R] ? JoinPathTupleImpl<AsPathTuple<R>, AsKey<K>> : never; type MapKeys<T> = { [K in keyof T as ToKey<K>]: T[K]; }; type TryAccess<T, K> = K extends keyof T ? T[K] : T extends null ? null : undefined; type TryAccessArray<T extends ReadonlyArray<any>, K extends Key> = K extends `${ArrayKey}` ? T[number] : TryAccess<T, K>; export type EvaluateKey<T, K extends Key> = T extends ReadonlyArray<any> ? IsTuple<T> extends true ? TryAccess<T, K> : TryAccessArray<T, K> : TryAccess<MapKeys<T>, K>; export type EvaluatePath<T, PT extends PathTuple> = PT extends [infer K, ...infer R] ? EvaluatePath<EvaluateKey<T, AsKey<K>>, AsPathTuple<R>> : T; export type TupleKeys<T extends ReadonlyArray<any>> = Exclude<keyof T, keyof any[]>; type NumericObjectKeys<T extends Traversable> = ToKey<Extract<keyof T, ArrayKey | `${ArrayKey}`>>; export type NumericKeys<T extends Traversable> = UnionToIntersection<T extends ReadonlyArray<any> ? (IsTuple<T> extends true ? [TupleKeys<T>] : [ToKey<ArrayKey>]) : [NumericObjectKeys<T>]>[never]; export type ObjectKeys<T extends Traversable> = Exclude<ToKey<keyof T>, `${string}.${string}` | "">; export type CheckKeyConstraint<T, K extends Key, U> = K extends any ? (EvaluateKey<T, K> extends U ? K : never) : never; export type ContainsIndexable<T> = IsNever<Extract<T, ReadonlyArray<any>>> extends true ? false : true; type KeysImpl<T> = [T] extends [Traversable] ? (ContainsIndexable<T> extends true ? NumericKeys<T> : ObjectKeys<T>) : never; export type Keys<T, U = unknown> = IsAny<T> extends true ? Key : IsNever<T> extends true ? Key : IsNever<NonNullable<T>> extends true ? never : CheckKeyConstraint<T, KeysImpl<NonNullable<T>>, U>; export type HasKey<T, K extends Key> = IsNever<Exclude<K, Keys<T>>>; type ValidPathPrefixImpl<T, PT extends PathTuple, VPT extends PathTuple> = PT extends [infer K, ...infer R] ? HasKey<T, AsKey<K>> extends true ? ValidPathPrefixImpl<EvaluateKey<T, AsKey<K>>, AsPathTuple<R>, AsPathTuple<[...VPT, K]>> : VPT : VPT; export type ValidPathPrefix<T, PT extends PathTuple> = ValidPathPrefixImpl<T, PT, []>; export type HasPath<T, PT extends PathTuple> = ValidPathPrefix<T, PT> extends PT ? true : false; export {};