/** * Types declared in this file will be globally available throughout the project. These should * be used sparsely and mainly for utility types (such as $Debug) that are likely unused outside * of being helper utilities. * * @note * If needing to `import` in this file, the global types must all be wrapped in * `declare global` or they will no longer be seen as global. */ /** * When running $Debug, these values will not be mapped into. One must be careful here as * interfaces do not often match with `extends` in Typescript (aka O[K] extends React.CSSProperties won't * work) */ type $DebugNoExtendValue<E> = | null | undefined | void | E | ((...args: any[]) => any); type $DebugDepth = 1 | 2 | 3 | 4 | 5; type $DebugDepthDefault = 5; /** * $Debug<Type> allows you to expand out types in a way that will allow you to see * exact properties of a type that will be the result of the final calculations * such as One & Two & { three: string } --> { one: string, two: string, three: string } * * @example * type PropsLink = CommonLinkProps & { * href: string; * target?: string | undefined; * className?: string | undefined; * style?: React.CSSProperties | undefined; * } & { * icon?: string | undefined; * } * * type CheckProps = $Debug<PropsLink> * * type CheckProps = { * color?: string | undefined; * type?: "secondary" | "primary" | "dark" | "error" | "success" | "light" | undefined; * children: React.ReactNode; * href: string; * target?: string | undefined; * className?: string | undefined; * style?: React.CSSProperties | undefined; * icon?: string | undefined; * } */ type $Debug<T, E = never> = T extends $DebugNoExtendValue<E> ? T : T extends object ? T extends infer O ? { [K in keyof O]: O[K]; } : never : T; /** * $DebugDeep<Type, Exclude, Depth> allows you to expand out types in a way that will allow you to see * exact properties of a type that will be the result of the final calculations. Depth will default to the * maximum levels (currently 5). * * You may exclude expansion of certain values by providing the `Exclude` option. If you want to define * Depth and not Exclude just provide `never`. * such as One & Two & { three: string } --> { one: string, two: string, three: string } * * @example * $DebugDeep<One & Two, SomeType>; // Don't expand values of SomeType if encountered * $DebugDeep<One & Two, never, 1>; // Expand one level into (One & Two) * $DebugDeep<One & Two, never, 4>; // Expand two levels into (One & Two) * $DebugDeep<One & Two>; // Expand maximum levels into (One & Two) */ type $DebugDeep< T, E = never, L extends $DebugDepth = $DebugDepthDefault > = T extends $DebugNoExtendValue<E> ? T : T extends object ? T extends infer O ? { [K in keyof O]: L extends 1 ? $DebugDeep1<O[K], E> : L extends 2 ? $DebugDeep2<O[K], E> : L extends 3 ? $DebugDeep3<O[K], E> : L extends 4 ? $DebugDeep4<O[K], E> : L extends 5 ? $DebugDeep5<O[K], E> : $DebugDeep<T, E, $DebugDepthDefault>; } : never : T; type $DebugDeep1<T, E = never> = T extends $DebugNoExtendValue<E> ? T : T extends object ? T extends infer O ? { [K in keyof O]: O[K]; } : never : T; type $DebugDeep2<T, E = never> = T extends $DebugNoExtendValue<E> ? T : T extends object ? T extends infer O ? { [K in keyof O]: $DebugDeep1<O[K], E>; } : never : T; type $DebugDeep3<T, E = never> = T extends $DebugNoExtendValue<E> ? T : T extends object ? T extends infer O ? { [K in keyof O]: $DebugDeep2<O[K], E>; } : never : T; type $DebugDeep4<T, E = never> = T extends $DebugNoExtendValue<E> ? T : T extends object ? T extends infer O ? { [K in keyof O]: $DebugDeep3<O[K], E>; } : never : T; type $DebugDeep5<T, E = never> = T extends $DebugNoExtendValue<E> ? T : T extends object ? T extends infer O ? { [K in keyof O]: $DebugDeep4<O[K], E>; } : never : T;