import { SnakeCase } from "type-fest"; import { Options as SnakeCaseOptions } from "snake-case"; // eslint-disable-next-line @typescript-eslint/ban-types type EmptyTuple = []; // Allow union with, for example, `undefined` and `null`. type ObjectUnion = Record | unknown; /** Return a default type if input type is nil. @template T - Input type. @template U - Default type. */ type WithDefault = T extends undefined | void | null ? U : T; /** Check if an element is included in a tuple. @template List - List of values. @template Target - Target to search. */ type Includes = List extends undefined ? false : List extends Readonly ? false : List extends readonly [infer First, ...infer Rest] ? First extends Target ? true : Includes : boolean; /** Append a segment to dot-notation path. @template S - Base path. @template Last - Additional path. */ type AppendPath = S extends "" ? Last : `${S}.${Last}`; declare namespace snakecaseKeys { /** Convert keys of an object to snake-case strings. @template T - Input object or array. @template Deep - Deep conversion flag. @template Exclude - Excluded keys. @template Path - Path of keys. */ export type SnakeCaseKeys< T extends ObjectUnion | ReadonlyArray>, Deep extends boolean = true, Exclude extends readonly unknown[] = EmptyTuple, Path extends string = "" > = T extends ReadonlyArray> ? // Handle arrays or tuples. { [P in keyof T]: T[P] extends Record | ReadonlyArray> ? SnakeCaseKeys : T[P]; } : T extends Record ? // Handle objects. { [P in keyof T as [Includes] extends [true] ? P : SnakeCase

]: [Deep] extends [true] ? T[P] extends ObjectUnion | ReadonlyArray> ? SnakeCaseKeys> : T[P] : T[P]; } : // Return anything else as-is. T; interface Options { /** Recurse nested objects and objects in arrays. @default true */ readonly deep?: boolean; /** Exclude keys from being snakeCased. @default [] */ readonly exclude?: ReadonlyArray; /** A function that determines whether to recurse for a specific key and value. */ readonly shouldRecurse?: { (key: any, value: any): boolean; } /** Options object that gets passed to snake-case parsing function. @default {} */ readonly parsingOptions?: SnakeCaseOptions; } } /** Convert object keys to snake using [`to-snake-case`](https://github.com/ianstormtaylor/to-snake-case). @param input - Object or array of objects to snake-case. @param options - Options of conversion. */ declare function snakecaseKeys< T extends Record | ReadonlyArray>, Options extends snakecaseKeys.Options >( input: T, options?: Options ): snakecaseKeys.SnakeCaseKeys< T, Options["deep"] extends boolean ? Options["deep"] : true, WithDefault >; export = snakecaseKeys;