/**
* Generic function type for type-safe function signatures.
*
* Enables consistent typing across utility functions and higher-order functions
* where function parameters need to be strongly typed.
*
* @example
* function memoize(fn: Func): Func
* function debounce(fn: Func, ms: number): Func
*/
export type Func = (...args: A) => R;
/**
* Generic async function type for type-safe async function signatures.
*
* Ensures Promise return types are properly handled in utility functions
* that work with async operations.
*
* @example
* function retry(fn: AsyncFunc, attempts: number): AsyncFunc
* function withTimeout(fn: AsyncFunc, ms: number): AsyncFunc
*/
export type AsyncFunc = (...args: A) => Promise;
/**
* Generic constructor type for class-based type operations.
*
* Enables type-safe operations on constructor functions and class factories.
*
* @example
* function createInstance(ctor: T, ...args: any[]): InstanceType
*/
export type ClassType = { new: Func }
/**
* Extracts only non-function properties from an object type.
*
* Essential for serialization, data persistence, and state management where
* only data properties should be included, not methods.
*
* @example
* interface User { id: string; name: string; save(): void; delete(): void; }
* type UserData = Pick>; // { id: string; name: string; }
*/
export type NonFunctionProps = { [K in keyof T]: T[K] extends Func | ClassType ? never : K }[keyof T];
/**
* Extracts only function properties from an object type.
*
* Useful for creating proxies, method decorators, or when separating
* behavior from data in object-oriented designs.
*
* @example
* interface User { id: string; name: string; save(): void; delete(): void; }
* type UserMethods = Pick>; // { save(): void; delete(): void; }
*/
export type FunctionProps = { [K in keyof T]: T[K] extends Func | ClassType ? K : never }[keyof T];
/**
* Makes all properties in a nested object optional recursively.
*
* Critical for partial update operations, configuration merging, and
* scenarios where deep object structures need incremental updates.
*
* @example
* interface Config { api: { url: string; timeout: number; }; ui: { theme: string; }; }
* function updateConfig(partial: DeepOptional): void
* updateConfig({ api: { timeout: 5000 } }); // Only timeout is required
*/
export type DeepOptional = {
[K in keyof T]?: T[K] extends object ? DeepOptional : T[K]
};
/**
* Makes all properties in an object nullable.
*
* Essential for database result types and API responses where fields
* can legitimately be null due to LEFT JOINs or missing data.
*
* @example
* interface User { id: string; email: string; profile: Profile; }
* type DatabaseUser = NullableObject; // All fields can be null
*/
export type NullableObject = {
[K in keyof T]: T[K] | null
};
/**
* Generates all possible dot-notation paths for an object type.
*
* Essential for autocomplete in configuration systems, form builders,
* and any API that accepts property paths as strings.
*
* @example
* interface User { profile: { name: string; age: number; }; tags: string[]; }
* type UserPaths = PathNames; // 'profile' | 'profile.name' | 'profile.age' | 'tags' | 'tags.0'
*/
export type PathNames = T extends object ? { [K in keyof T]:
`${Exclude}${"" | `.${
T[K] extends Set
? SetValue extends object
? `${number}` | `${number}.${PathNames}` // "set.0.subtype"
: `${number}` // "set.0"
: T[K] extends Map
? MapValue extends object
? MapKey extends string | number
? `${MapKey}` | `${MapKey}.${PathNames}` // "map.key.subtype"
: string | `${string}.${PathNames}` // "map.string.subtype" (fallback)
: MapKey extends string | number
? `${MapKey}` // "map.key"
: string // "map.string"
: T[K] extends any[]
? T[K] extends (infer U)[]
? U extends object
? `${number}` | `${number}.${PathNames}`
: `${number}`
: `${number}`
: PathNames
}`}`
}[keyof T] : never
/**
* Generates only the leaf paths (final values) for an object type.
*
* Useful for validation systems and data mapping where you only care
* about paths that lead to actual values, not intermediate objects.
*
* @example
* interface User { profile: { name: string; age: number; }; }
* type UserLeaves = PathLeaves; // 'profile.name' | 'profile.age'
*/
export type PathLeaves = T extends object ? {
[K in keyof T]-?: (
T[K] extends undefined
? never
: `${Exclude}${PathLeaves extends never ? "" : `.${PathLeaves}`}`
)
}[keyof T] : never
/**
* Extracts the value type at a specific string path.
*
* Enables type-safe deep property access with compile-time validation
* of both path validity and return type correctness. Supports:
* - Regular object property access
* - Array/tuple index access
* - Map key access
* - Set index access
*
* @example
* interface User {
* profile: { name: string; age: number; };
* tags: Set;
* metadata: Map;
* }
* type UserName = PathValue; // string
* type Tag = PathValue; // string
* type MetaValue = PathValue; // string
*/
export type PathValue =
P extends `${infer Key}.${infer Rest}`
? Key extends keyof T
? PathValue
: T extends Map
? K extends string | number
? Key extends `${K}`
? PathValue
: never
: PathValue
: T extends Set
? Key extends `${number}`
? PathValue
: never
: T extends any[]
? Key extends `${number}`
? T extends (infer U)[]
? PathValue
: never
: never
: never
: P extends keyof T
? T[P]
: T extends Map
? K extends string | number
? P extends `${K}`
? V
: never
: V
: T extends Set
? P extends `${number}`
? V
: never
: T extends any[]
? P extends `${number}`
? T extends (infer U)[]
? U
: never
: never
: never;
/**
* Union of string and number types.
*
* Commonly used for object keys, array indices, and ID types that
* can be either string or numeric.
*
* @example
* function getItem(collection: Record, key: StrOrNum): T | undefined
*/
export type StrOrNum = string | number
/**
* Represents either a single item or an array of items.
*
* Essential for flexible APIs that accept both individual items and
* collections, reducing the need for separate method overloads.
*
* @example
* function addClass(elements: OneOrMany, className: string): void
* addClass(document.body, 'active'); // single element
* addClass([el1, el2], 'active'); // multiple elements
*/
export type OneOrMany = T | T[];
/**
* Object with string keys and string values.
*
* Standard type for configuration objects, HTTP headers, query parameters,
* and any key-value mapping that should be serializable.
*
* @example
* function buildQueryString(params: StringProps): string
* function setAttributes(element: Element, attrs: StringProps): void
*/
export interface StringProps { [key: string]: string };
/**
* Object with string keys and boolean values.
*
* Perfect for feature flags, permission sets, validation results,
* and any boolean configuration mapping.
*
* @example
* function checkPermissions(user: User): BoolProps // { canRead: true, canWrite: false }
* function validateForm(data: FormData): BoolProps // { emailValid: true, nameValid: false }
*/
export interface BoolProps { [key: string]: boolean };
/**
* Represents a value that can be either synchronous or asynchronous.
*
* Critical for utility functions that need to handle both sync and async
* operations uniformly, enabling flexible API design.
*
* @example
* function processData(processor: () => MaybePromise): Promise
* function transform(value: T, transformer: (val: T) => MaybePromise): Promise
*/
export type MaybePromise = T | Promise;
/**
* Filters out undefined from a union type.
*
* Essential for type narrowing operations and ensuring required values
* in contexts where undefined is not acceptable.
*
* @example
* function requireValue(value: T | undefined): NotUndefined
* type RequiredFields = { [K in keyof T]: NotUndefined }
*/
export type NotUndefined = T extends undefined ? never : T;
/**
* Union of all JavaScript falsy values.
*
* Comprehensive type for conditional logic, validation functions,
* and type guards that need to handle all falsy cases.
*
* @example
* function isFalsy(value: unknown): value is Falsy
* function removeEmpty(arr: (T | Falsy)[]): T[]
*/
export type Falsy = number | false | "" | bigint | null | undefined;
/**
* Filters out falsy values from a type.
*
* Enables type-safe operations on values that are guaranteed to be
* truthy, eliminating the need for runtime falsy checks.
*
* @example
* function assertTruthy(value: T): asserts value is Truthy
* function compact(arr: T[]): Truthy[]
*/
export type Truthy = T extends Falsy ? never : T;