/**
 * Used to display an error message instead of never, for better readability
 * @export type {Message}
 */
type Message<T extends string> = T;
/**
 *
 * Represents a type that can either be  ``null`` or ``undefined``.
 * @export type {Nullable}
 */
type Nullable = null | undefined;
/**
 * Represents a  type that can hold any numeric value: number or a bigint.
 * @export type {Numeric}
 */
type Numeric = number | bigint;
/**
 * Represents all the primitive types in JavaScript.
 * - `Nullable`: A value that can be either null or undefined.
 * - `Numeric`: A value that can be either a number or a bigint.
 * - `string`: Represents textual data.
 * - `boolean`: Represents a logical value (true or false).
 * - `symbol`: Represents a unique and immutable value.
 */
type Primitive = string | boolean | symbol | Nullable | Numeric;
/**
 * Represents a type that includes falsy values in JavaScript.
 * Falsy values are those that coerce to false when used in a boolean context.
 * This includes `false`, an empty string (`''`), numeric zero (`0`), `null`,
 * and `undefined`.
 */
type Falsy = false | '' | 0 | Nullable;
/**
 * This type is used to describe constructor functions or classes
 * that can be invoked using the `new` keyword.
 */
type Newable = {
    new (...args: any[]): any;
};
/**
 * Describes any function accepting any arguments
 *  and returning any value.
 */
type AnyFunction = (...args: any[]) => any;
/**
 * Describes any function accepting and retruning `unknown`s
 */
type UnknownFunction = (...args: unknown[]) => unknown;
/**
 * `Optional<T>` is similar to Python's `Optional` and Rust's `Option` types.
 * It promotes more predictable code,
 * by enforcing explicit handling of optional scenarios, e.g: requiring functions
 * to return `null` specifically when a value is absent.
 */
type Optional<T> = T | null;
/**
 Represnets a type that might be nullable, as in it might be `null` or `undefined`.
*/
type Maybe<T> = T | Nullable;
type MaybeUnknown<T> = T | unknown;
type MaybeUndefined<T> = T | undefined;
/**
 * Presents any non-nullish value
 */
type EmptyObject = NonNullable<unknown>;
/**
 * Represents a type that is not assignable to `V`.
 * @example
 */
type NotAssignableTo<U, V> = U extends V ? never : U;

/**
 * Conditional type: if the condition `C` is `true`, return `Do`, otherwise return `Else`.
 * @example
 * ````ts
   If<IsNever<never>, true, false>; // true
   If<Not<IsNever<never>>, true, false>; // false
 * ````
*/
type If<C extends boolean, Do, Else> = C extends true ? Do : Else;
/**
 * Negates a boolean type `B`.
 * @example
   Not<true>; // false
   Not<false>; // true
*/
type Not<B extends boolean> = B extends true ? false : true;
/**
 * Logical AND between two boolean types `B1` and `B2`.
 * @example
   And<true, false>; // false
   And<true, true>; // true
*/
type And<B1 extends boolean, B2 extends boolean> = If<B1, If<B2, true, false>, false>;
/**
 * Logical OR between two boolean types `B1` and `B2`.
 * @example
   Or<true, false>; // true
   Or<false, false>; // false
*/
type Or<B1 extends boolean, B2 extends boolean> = If<B1, true, If<B2, true, false>>;
/**
 * Logical NOR between two boolean types `B1` and `B2`.
 * Evaluates to `true` only if both `B1` and `B2` are `false`.
 * @example
   Nor<false, false>; // true
   Nor<true, false>; // false
   Nor<false, true>; // false
   Nor<true, true>; // false
*/
type Nor<A extends boolean, B extends boolean> = Not<Or<A, B>>;
/**
 * Exclusive OR (XOR) between two boolean types `B1` and `B2`.
 * @example
   Xor<true, false>; // true
   Xor<true, true>; // false
*/
type Xor<B1 extends boolean, B2 extends boolean> = Or<And<B1, Not<B2>>, And<Not<B1>, B2>>;
/**
 * Logical NAND between two boolean types `B1` and `B2`.
 * @example
   Nand<true, false>; // true
   Nand<true, true>; // false
*/
type Nand<B1 extends boolean, B2 extends boolean> = Not<And<B1, B2>>;
/**
 * Logical XNOR between two boolean types `A` and `B`.
 * @example
   Xnor<true, false>; // false
   Xnor<true, true>; // true
*/
type Xnor<A extends boolean, B extends boolean> = Not<Xor<A, B>>;
/**
 * Logical XAND between two boolean types `A` and `B`. (basically NOR)
 * @example
   Xand<false, false>; // true
   Xand<true, false>; // false
   Xand<false, true>; // false
   Xand<true, true>; // false
 */
type Xand<A extends boolean, B extends boolean> = Not<Xor<A, B>>;
/**
 * Conditional  type that checks if  type `T` extends  type `P`.
 * If `T` extends `P`, the  type resolves to `Do`; otherwise `Else`.
 * @example
 *  type Result1 = IfExtends<string, string | number, true, false>; // is true
 *  type Result2 = IfExtends<number, string | number, true, false>; // is true
 *  type Result3 = IfExtends<boolean, string | number, true, false>; // is false
 *
 *  type IsString<T> = IfExtends<T, string, true, false>;
 *  type IsNumber<T> = IfExtends<T, number, true, false>;
 *
 *  type TestString = IsString<string>; // is true
 *  type TestNumber = IsNumber<number>; // is true
 *  type TestBoolean = IsNumber<boolean>; // is false
 */
type IfExtends<T, P, Do, Else> = T extends P ? Do : Else;
/**
 * Conditional type that checks if type `T` is equal to type `P`.
 * If `T` is equal to `P`, the type resolves to `Do`, otherwise `Else`.
 * @example
 *  type Result1 = IfEquals<string, string, true, false>; // is true
 *  type Result2 = IfEquals<number, string, true, false>; // is false
 *  type Result3 = IfEquals<boolean, boolean, true, false>; // is true
 *
 *  type IsExactlyString<T> = IfEquals<T, string, true, false>;
 *  type IsExactlyNumber<T> = IfEquals<T, number, true, false>;
 *
 *  type TestString = IsExactlyString<string>; // is true
 *  type TestNumber = IsExactlyNumber<number>; // is false
 *  type TestBoolean = IsExactlyString<boolean>; // is false
 */
type IfEquals<T, P, Do, Else> = Equals<T, P> extends true ? Do : Else;
/**
 * Conditional  type that checks if two types `X` and `Y` are exactly equal.
 * If `X` is equal to `Y`, the  type resolves to `true`; otherwise `false`.
 * @example
 *  type Result1 = Equals<string, string>; // is true
 *  type Result2 = Equals<number, string>; // is false
 *  type Result3 = Equals<boolean | string, string | boolean>; // is true
 */
type Equals<X, Y> = (<T>() => T extends X ? true : false) extends <T>() => T extends Y ? true : false ? true : false;

/**
 * As the name implies, it turns a union into an intersection
 * @example
  type T = NewType<'T', string>;
  type Result = UnionToIntersection<
      (() => 'foo') | ((baz: 88) => Optional<NewType<'T', string>>)
    >
    // Result: (() => 'foo') & ((baz: 88) => Optional<T>)

    type Result2 = UnionToIntersection<
      IsFalsy<0> | IsDeepImmutable<{ a: string; readonly b: string }>
    >
    // Result 2: IsFalsy<0> & IsDeepImmutable<{ a: string; readonly b: string }> => true & true => evaluates to true
 *
 */
type UnionToIntersection<U> = (U extends unknown ? (arg: U) => unknown : never) extends (arg: infer I) => void ? I : never;

type LastOf<T> = UnionToIntersection<T extends any ? () => T : never> extends () => infer R ? R : never;
/**
 * `UnionToTuple<T>` converts a union type `T` into a tuple type while preserving the order.
 * This type is useful for scenarios where you need to work with the individual members of a union as an ordered list.
 *
 * @template T - The union type to convert into a tuple.
 * @template L - The last member of the union, used for recursive extraction.
 * @template N - A boolean that checks if the union is empty.
 *
 * @example
 * type TestUnion = 'a' | 'b' | 'c';
 * type ResultTuple = UnionToTuple<TestUnion>; // Result: ['a', 'b', 'c']
 */
type UnionToTuple<T, L = LastOf<T>, N = [T] extends [never] ? true : false> = N extends true ? [] : [...UnionToTuple<Exclude<T, L>>, L];

/**
 * Represents the keys of a given  type `T`.
 * This  type alias `Keys<T>` is equivalent to `keyof T`,
 * which retrieves the union  type of keys (property names) of  type `T`.
 * @returns Union  type of keys (property names) of  type `T`.
 * @example
 *  type Person = {
 *   name: string;
 *   age: number;
 *   email: string;
 * };
 *
 *  type PersonKeys = Keys<Person>; => "name" | "age" | "email"
 */
type Keys<T> = keyof T;
/**
 * Represents the union  type of values of properties in a given  type `T`.
 * This  type alias `Vals<T>` retrieves the union  type of values corresponding
 * to the keys (property names) of  type `T`.
 * @example
 *  type Person = {
 *   name: string;
 *   age: number;
 *   email: string;
 * };
 *
 *  type PersonValues = Vals<Person>; => string | number
 */
type Vals<T> = T[Keys<T>];
/**
 * Extracts keys from a type `T` that represent required properties.
 * Properties that are not marked with `?`.
 * @example
 * ```ts
 * type T = RequiredKeys<{ a: number; b?: string }> // Result:  'a'
 * ```
 */
type RequiredKeys<T> = {
    [K in Keys<T>]-?: IfExtends<EmptyObject, Pick<T, K>, never, K>;
}[Keys<T>];
/**
 * Why not call it ``OptionalKeys``?
 * ``Optional<T>`` in this library represents a type ``T`` that can be either ``T`` or ``null``. So creating
 * ``OptionalKeys`` type would entail removing any type that can be null, which is not the intention here.
 *
 * ``NonRequiredKeys<T>`` simply removes non required keys, as in any property of an object that is
 * marked with `?` operator
 * @example
 * ```ts
 * type T = NonRequiredKeys<{ a: number; b?: string }> // Result:  'b'
 * ```
 */
type NonRequiredKeys<T> = Exclude<Keys<T>, RequiredKeys<T>>;

/**
 * Represents a  type that can either be a single value of  type `T` or an array of values of  type `T`.
 * @example
 * type T1 = EitherOneOrMany<number>; 10; // Valid
 * type T2 = EitherOneOrMany<number>;  [20, 30]; // Also valid
 */
type EitherOneOrMany<T> = T | T[];
/**
 * Checks if a given type `T` is `Falsy`.
 * @returns `true` if `T` is a subtype of `Falsy`, otherwise `false`.
 * @example
 * type Falsy = IsFalsy<''>; // TestFalsy is tru`
 * type Truthy = IsFalsy<10>; // TestTruthy is false
 */
type IsFalsy<T> = IfExtends<T, Falsy, true, false>;
/**
 * Checks if a given  type `T` is a truthy value.
 * A truthy value is any value that is not a falsy value.
 * @returns `true` if `T` is not a subtype of `Falsy`, otherwise `false`.
 * @example
 *  type TruthyString = IsTruthy<string>; // => true
 *  type TruthyNumber = IsTruthy<10>; // => true
 *  type FalsyNull = IsTruthy<null>; // => false
 *  type FalsyEmptyString = IsTruthy<''>; => false
 */
type IsTruthy<T> = IfExtends<T, Exclude<T, Falsy>, true, false>;
/**
 * Checks if a given  type `T` is `never`.
 * The `never`  type represents a value that never occurs,
 * for example a function that always errors out.
 * @returns `true` if `T` is `never`, otherwise `false`.
 * @example
 *  type Never = IsNever<never>; => true
 *  type NotNever = IsNever<string>; => false
 */
type IsNever<T> = Equals<T, never>;
/**
 * A nullable type is a type that might be null, undefined or both
 * @returns
 * `true` if it is, else `false`
 */
type IsNullable<T> = IfExtends<T, Nullable, true, false>;
/**
 * Checks if a given  type `T` is `unknown`.
 *
 * Values of  type `unknown` can hold any value, similar to `any`, but with stricter  type safety.
 * Unlike `any`, you cannot perform operations directly on values of  type `unknown`
 * without  type assertion or  type narrowing.
 * @returns `true` if `T` is `unknown`, otherwise `false`.
 * @example
 *  type IsUnknownValue = IsUnknown<unknown>; //  true
 *  type IsNotUnknownValue = IsUnknown<string>; // also true
 * @remarks
 * > If you want `unknown` to be exact, use `IsExactlyUnknown`
 */
type IsUnknown<T> = IfExtends<T, unknown, true, false>;
/**
 * Checks if a given  type `T` is exactly `unknown`.
 * @example
 * ````ts
  IsExactlyUnknown<any | unknown>; // false, since the union evaluates to any
  IsExactlyAny<any | unknown>; // true
  IsExactlyUnknown<unknown | string> // true
  IsExactlyUnknown<string>; // flase
 * ````
 */
type IsExactlyUnknown<T> = Equals<T, unknown>;
/**
 * @returns `true` if `T` is `string`, otherwise `false`.
 */
type IsString<T> = IfExtends<T, string, true, false>;
/**
 * @returns `true` if `T` is excatly `string`, otherwise `false`.
 * @example
 * ````ts
  IsExactlyString<number>; //  false;
  IsExactlyString<any | string>; // false
  IsExactlyString<unknown | string>; //  false
 * ````
 */
type IsExactlyString<T> = Equals<T, string>;
/**
 * @returns `true` if `T` is `boolean`, otherwise `false`.
 */
type IsBoolean<T> = IfExtends<T, boolean, true, false>;
/**
 * A numeric type iincludes `number` and `bigint`.
 * @returns `true` if `T` is a numeric type, otherwise `false`.
 */
type IsNumeric<T> = IfExtends<T, Numeric, true, false>;
/**
 * Is a given type `T` an array?
 * @returns `true` if `T` it is, otherwise `false`.
 * @example
 * ```
 * IsArray<number[]>; // true
 * IsArray<string>; // false
 * ```
 */
type IsArray<T> = IfExtends<T, unknown[], true, false>;
/**
 * Type utility that checks if a given type `T` is an `AnyFunction` (any function type).
 * @template T The type to check.
 * @returns `true` if `T` is an `AnyFunction`, otherwise `false`.
 * An `AnyFunction` is defined as a function type that accepts any arguments and returns any value.
 * @example
 * ```
 * IsAnyFunction<() => void>; // true (matches AnyFunction)
 * IsAnyFunction<(x: number) => string>; // true (matches AnyFunction)
 * IsAnyFunction<string>; // false (string is not a function type)
 * ```
 */
type IsAnyFunction<T> = IfExtends<T, AnyFunction, true, false>;
/**
 * Type utility that checks if a given type `T` is a `Function` (function type accepting `unknown` arguments and returning `unknown`).
 * @template T The type to check.
 * @returns `true` if `T` is a `Function`, otherwise `false`.
 * A `Function` is defined as a function type that accepts arguments of type `unknown` and returns a value of type `unknown`.
 * @example
 * ```
 * IsFunction<() => void>; // true (matches Function)
 * IsFunction<(x: number) => string>; // true (matches Function)
 * IsFunction<string>; // false (string is not a function type)
 * ```
 */
type IsFunction<T> = IfExtends<T, UnknownFunction, true, false>;
/**
 * Checks if a given type `T` qualifies as an object.
 * @returns `true` if it is, otherwise `false`.
 * An object in this context is defined as a non-null object (excluding functions and arrays).
 * @example
 * ```
  IsObject<object>; // true
  IsObject<{ name: string }>; // true
  IsObject<string>; // false
  IsObject<Function>; // true, yes, the built-in Function type is an interface with a bunch of methods, so yes it's an object.
  // if you want to use the function type use this:
  IsObject<UnknownFunction>; // false
  // or this
  IsObject<AnyFunction>; // false
  IsObject<any[]>; // false
  IsObject<null>; // false
 * ```
 */
type IsObject<T> = And<IfExtends<T, object, true, false>, And<Not<IsFunction<T>>, Not<IsArray<T>>>>;
/**
 * @returns `true` if `T` is `number`, otherwise `false`.
 */
type IsNumber<T> = IfExtends<T, number, true, false>;
/**
 * @returns `true` if `T` is exactly of type `number`, otherwise `false`.
 * @example
 * ````ts
  IsExactlyNumber<any | number>; // false
  IsExactlyNumber<unknown | number> // false
  IsExactlyNumber<number> // true
  IsExactlyNumber<87> // false
 * ````
 */
type IsExactlyNumber<T> = Equals<T, number>;
/**
 * @returns `true` if `T` is `bigint`, otherwise `false`.
 */
type IsBigInt<T> = IfExtends<T, bigint, true, false>;
/**
 * @returns `true` if `T` is exactly `bigint`, otherwise `false`.
 * @example
 * ````ts
  IsBigInt<unknown | bigint>; // false
  IsBigInt<symbol | Nullable>; // false
  IsBigInt<bigint>; // true
 * ````
 */
type IsExactlyBigInt<T> = Equals<T, bigint>;
/**
 * @returns `true` if `T` is `symbol`, otherwise `false`.
 */
type IsSymbol<T> = T extends symbol ? true : false;
/**
 * @returns `true` if `T` is exactly `symbol`, otherwise `false`.
 * @example
 * ````ts
  IsExactlySymbol<symbol>; // true
  IsExactlySymbol<any | symbol>; // false
  IsExactlySymbol<Integer<2>>; // false
 * ````
 */
type IsExactlySymbol<T> = Equals<T, symbol>;
/**
 * If ``T`` is exactly``any``, return ``true``, otherwise, return ``false``.
 * @example
 * ````ts
  IsExactlyAny<any | Nullable>; // true, once unsafe, always unsafe
  IsExactlyAny<Numeric | Nullable>; // false
  IsExactlyAny<unknown>; // false
  IsExactlyAny<any>, true
 * ````
 */
type IsExactlyAny<T> = Equals<T, any>;
/**
 * @returns `true` if `T` is a `Newable`, otherwise `false`.
 */
type IsNewable<T> = IfExtends<T, Newable, true, false>;
/**
 * A  type that excludes `null` and `undefined` from  type `T`.
 * @example
 * Type Str = ExcludeNullable<string | null> //  string
 * Type Str2 = ExcludeNullable<string | null | undefined> //  string
 * Type Str3 = ExcludeNullable<string | undefined> //  string
 *
 */
type ExcludeNullable<T> = Exclude<T, Nullable>;
/**
 * A  type that excludes `undefined` from  type `T`.
 * @example
 * Type Str = ExcludeNullable<string | undefined> // Result:  string
 */
type ExcludeUndefined<T> = Exclude<T, undefined>;
/**
 * A  type that excludes `null` from  type `T`.
 * @example
 * Type Str = ExcludeNullable<string | null> // Result:  string
 */
type ExcludeNull<T> = Exclude<T, null>;
/**
 * Evaluates whether one type `T` is assignable to another type `U`.
 * @returns `true` if `T` is assignable to `U`, `false` otherwise.
 *
 * @example
 * ```typescript
 * type A = { x: number };
 * type B = { x: number; y: string };
 * type C = { x: number; y?: string };
 *
 * type Check1 = Extends<A, B>; // false, A does not extend B
 * type Check2 = Extends<B, A>; // true, B extends A
 * type Check3 = Extends<C, B>; // true, C extends B
 * ```
 */
type Extends<T, U> = T extends never ? false : T extends U ? true : false;
/**
 * `Simplify<T>` flattens the structure of a given type by resolving intersections
 * and reducing redundant wrapping, making complex types easier to work with.
 * This type is particularly helpful for deeply nested mapped types, where
 * readability and simplicity of the resulting type is crucial.
 *
 * @template T - The type to simplify.
 *
 * @example
 * ```ts
 * type Flattened = Simplify<{ a: string } & { b: number }>; // Result: { a: string; b: number }
 * ```
 */
type Simplify<T> = {
    [KeyType in Keys<T>]: T[KeyType];
} & EmptyObject;
/**
 * `PartialExcept<T, K extends keyof T>` is a utility type that makes all properties of `T` optional
 * except for the properties specified in `K`, which are required. This is useful for scenarios
 * where you want to enforce that certain fields must be present while allowing others to be omitted.
 *
 * @template T - The original type from which to derive the new type.
 * @template K - A subset of keys from `T` that should remain required in the resulting type.
 *
 * @example
 * ```ts
 * type User = {
 *   id: number;
 *   name: string;
 *   email: string;
 * };
 *
 * type UserUpdate = PartialExcept<User, 'email'>; // Result: { id?: number; name?: string; email: string; }
 * ```
 */
type PartialExcept<T, K extends keyof T> = {
    [P in K]: T[P];
} & Partial<Omit<T, K>>;
/**
 * Recursively resolves all nested `Promise` types to their underlying value.
 * Useful when dealing with complex, deeply nested promise chains.
 *
 * @example
 * type A = Promise<Promise<Promise<string>>>;
 * type B = DeepAwaited<A>; // Result: string
 */
type DeepAwaited<T> = T extends Promise<infer U> ? DeepAwaited<U> : T;

type KeysOfUnion$1<T> = T extends T ? keyof T : never;
/**
 * `ExclusiveUnion<T>` creates a union type where each member has its own properties as required,
 * while properties from other members of the union are made optional and set to `undefined`.
 * This is useful for cases where different configurations or variants in a union require only their specific fields.
 *
 * @template T - The union of object types for which partially optionalized variants should be created.
 * @template AllKeys - The union of all possible keys across the union's types, derived from `KeysOfUnion`.
 *
 * @example
 * ```ts
 * type Config = ExclusiveUnion<
 *   | { dbConnectionString: string; maxConnections: number }
 *   | { apiEndpoint: string; apiKey: string }
 *   | { storageBucket: string; accessKeyId: string; secretAccessKey: string }
 * >;
 *
 * // Example usage:
 * function configureService(config: Config) {
 *   if (config.dbConnectionString) {
 *     console.log(`Configuring database with connection string ${config.dbConnectionString}`);
 *   } else if (config.apiEndpoint) {
 *     console.log(`Configuring API with endpoint ${config.apiEndpoint}`);
 *   } else if (config.storageBucket && config.accessKeyId && config.secretAccessKey) {
 *     console.log(`Configuring storage bucket ${config.storageBucket}`);
 *   } else {
 *     console.log('Invalid configuration');
 *   }
 * }
 *
 * configureService({ dbConnectionString: 'postgres://...', maxConnections: 100 });
 * configureService({ apiEndpoint: 'https://api.example.com', apiKey: '1234' });
 * configureService({ storageBucket: 'my-bucket', accessKeyId: 'AKIA...', secretAccessKey: 'abcd' });
 * ```
 */
type ExclusiveUnion<T extends object, AllKeys extends KeysOfUnion$1<T> = KeysOfUnion$1<T>> = Simplify<T extends unknown ? T & Partial<Record<Exclude<AllKeys, Keys<T>>, undefined>> : never>;

/**
 * `KeysOfUnion` extracts the union of keys from a given union of object types.
 * This is useful in scenarios where you need to access all possible keys across
 * unioned object types within conditional or mapped types.
 *
 * @template T - The union of object types to extract keys from.
 *
 * @example
 * ```ts
 * type UnionKeys = KeysOfUnion<{ a: string } | { b: number }>; // Result: 'a' | 'b'
 * ```
 */
type KeysOfUnion<T> = T extends T ? keyof T : never;

/**
 * Turns a given primitive value (except symbol) into its string representation
 * @example
 * ```ts
 * StringifyPrimitive<45> //  "45"
 * StringifyPrimitive<boolean> //  "false" | "true"
 * StringifyPrimitive<null> // "null"
 * StringifyPrimitive<undefined> // "undefined"
 * ```
 */
type StringifyPrimitive<P extends Exclude<Primitive, symbol>> = `${P}`;
/**
 * Turn a given string literal to a numeric
 * @example
 * ````ts`
 * NumerifyString<'54'>; // 54
 * NumerifyString<'699620.000000001'>; // 699620.000000001
 * IsNegativeFloat<NumerifyString<'-699620.000000001'>>; // true
 * ````
 */
type NumerifyString$2<S extends string> = S extends `${infer N extends Numeric}` ? N : never;

/**
 * Checks if a given numeric value is in ]-∞,0[
 * @returns
 * true if it is, otherwise false
 */
type IsNegative<N extends Numeric> = StringifyPrimitive<N> extends `-${infer U}` ? true : false;
/**
 * Checks if a given numeric value is in [0,+∞[
 * @returns
 * true if it is, otherwise false
 */
type IsPositive<N extends Numeric> = N extends N ? Numeric extends N ? boolean : `${N}` extends `-${Numeric}` ? false : true : never;
/**
 * Check if a given numeric value is an integer
 * @returns
 * true if it is, else false
 */
type IsInteger<N extends Numeric> = number extends N ? false | true : N extends N ? `${N}` extends `${string}.${string}` ? false : true : never;
/**
 * Check if a given numeric value is an float
 * @returns
 * true if it is, else false
 */
type IsFloat<N extends Numeric> = number extends N ? false | true : N extends N ? `${N}` extends `${string}.${string}` ? true : false : never;
/**
 * Get the absolute value of a numeric N
 * @example
 * ```ts
 * Abs<-54>; // Result: 54
 * Abs<54>; // Result: 54
 * ```
 * @returns
 * |N|
 */
type Abs<N extends Numeric> = `${N}` extends `-${infer M extends Numeric}` ? M : N;

/**
 * Represents an integer type.
 * This type is used to ensure that a numeric value is an integer.
 *
 * Example use case:
 *
 * ```ts
 * export function myFunc<T extends Numeric>(a: Integer<T>) {
 *   console.log(a);
 * }
 * const good = myFunc(4545); // This is valid as 4545 is an integer.
 * const bad = myFunc(4545.554); // This will throw an error as 4545.554 is not an integer.
 * ```
 */
type Integer<N extends Numeric> = IfEquals<IsInteger<N>, true, N, never>;
/**
 * Type representing an integer that's in [0,+∞[
 */
type PositiveInteger<N extends Numeric> = IfEquals<IsPositiveInteger<N>, true, Integer<N>, never>;
/**
 * Represents a positive integer parsed from a string.
 * If the string does not represent a positive integer, it resolves to `never`, else
 * it resolves to its integer representation.
 * @example
 * ````ts
    PositiveIntegerString<'0'>; // works
    PositiveIntegerString<'82739283293237'>; // works
    PositiveIntegerString<'82739.283293237'>; // never
    PositiveIntegerString<'-82739.283293237'>; // never
    PositiveIntegerString<'-1'>; // never
 * ````
 */
type PositiveIntegerString<S extends string> = IfEquals<IsPositiveInteger<Integer<NumerifyString$1<S>>>, true, Integer<NumerifyString$1<S>>, never>;
/**
 * Type representing an integer that's in ]-∞, 0[
 */
type NegativeInteger<N extends Numeric> = IfEquals<IsNegativeInteger<N>, true, Integer<N>, never>;
/**
 * Represents a negative integer parsed from a string.
 * If the string does not represent a negative integer, it resolves to `never`, else
 * it resolves to its integer representation.
 * @example
 * ````ts
    NegativeIntegerString<'0'>; // never
    NegativeIntegerString<'82739283293237'>; // never
    NegativeIntegerString<'-82739.283293237'>; // works
    NegativeIntegerString<'-82739.283293237'>; // never
    NegativeIntegerString<'-1'>; // works
 * ````
 */
type NegativeIntegerString<S extends string> = IfEquals<IsNegativeInteger<Integer<NumerifyString$1<S>>>, true, Integer<NumerifyString$1<S>>, never>;
/**
 * Is it a negative integer ?
 * @return
 * `true` if it is, else `false`
 */
type IsNegativeInteger<N extends Numeric> = IsNegative<Integer<N>>;
/**
 * Is it a positive integer ?
 * @return
 * `true` if it is, else `false`
 */
type IsPositiveInteger<N extends Numeric> = IsPositive<Integer<N>>;
type NumerifyString$1<S extends string> = S extends `${infer N extends Numeric}` ? N : never;

/**
 * Type representing a float
 */
type Float<N extends Numeric> = IfExtends<IsFloat<N>, true, N, never>;
/**
 * Type representing a float that's in [0,+∞[
 */
type PositiveFloat<N extends Numeric> = IfEquals<IsPositiveFloat<N>, true, Float<N>, never>;
/**
 * Represents a positive float parsed from a string.
 * If the string does not represent a positive float, it resolves to `never`, else
 * it resolves to its float representation.
 * @example
 * ````ts
    PositiveFloatString<'0'>; // never
    PositiveFloatString<'82739283293237'>; // works
    PositiveFloatString<'-82739.283293237'>; // never
    PositiveFloatString<'-1'>; // never
    PositiveFloatString<'1.98'>; // works
    PositiveFloatString<'-1.98'>; // never
 * ````
 */
type PositiveFloatString<S extends string> = IfEquals<IsPositiveFloat<Float<NumerifyString<S>>>, true, Float<NumerifyString<S>>, never>;
/**
 * Type representing a float that's in ]-∞, 0[
 */
type NegativeFloat<N extends Numeric> = IfEquals<IsNegativeFloat<N>, true, Float<N>, never>;
/**
 * Represents a negative float parsed from a string.
 * If the string does not represent a negative float, it resolves to `never`, else
 * it resolves to its float representation.
 * @example
 * ````ts
    NegativeFloatString<'0'>; // never
    NegativeFloatString<'82739283293237'>; // never
    NegativeFloatString<'-82739.283293237'>; // works
    NegativeFloatString<'-1'>; // never
    NegativeFloatString<'-1.98'>; // works
 * ````
 */
type NegativeFloatString<S extends string> = IfEquals<IsNegativeFloat<Float<NumerifyString<S>>>, true, Float<NumerifyString<S>>, never>;
/**
 * Is it a negative float ?
 * @return
 * `true` if it is, else `false`
 */
type IsNegativeFloat<N extends Numeric> = IsNegative<Float<N>>;
/**
 * Is it a positive float ?
 * @return
 * `true` if it is, else `false`
 */
type IsPositiveFloat<N extends Numeric> = IsPositive<Float<N>>;
type NumerifyString<S extends string> = S extends `${infer N extends Numeric}` ? N : never;

/**
 * Represents an odd numeric?
 * @example
 * ````ts
 * Odd<2587967>; // 2587967
 * Odd<215848141>; // 215848141
 * Odd<200000000000000>; // never
 * Odd<200000000000000.55>; // never
 * Odd<200000000000001.53>; // never
 * ````
 */
type Odd<T extends Numeric> = IfExtends<StringifyPrimitive<Integer<T>>, `${Numeric | ''}${1 | 3 | 5 | 7 | 9}`, T, never>;
/**
 * Represents an even numeric
 * @example
 * ````ts
 * Even<200000000000000>; // 258796
 * Even<258796>; // 258796
 * Even<2000000000000001>; // never
 * ````
 */
type Even<T extends Numeric> = IfExtends<StringifyPrimitive<Integer<T>>, `${Numeric | ''}${2 | 4 | 6 | 8 | 0}`, T, never>;

/**
 * A type mapping interface that enables incremental type-level arithmetic operations.
 * This interface maps each number from 0 to 32,767 to its successor (n + 1),
 * enabling compile-time numeric operations in TypeScript's type system.
 *
 * @remarks
 * This interface is primarily used as a helper for other type utilities that need
 * to perform incremental operations, such as the `PositiveRange` type utility.
 * The mapping is limited to numbers up to 32,768 due to TypeScript's computational limits.
 *
 * @example
 * ```typescript
 * type Next = NumberMap[5]; // Results in: 6
 * type Invalid = NumberMap[32769]; // Results in: never
 * ```
 *
 * @internal
 * This interface is not intended to be used directly by consumers of the library.
 */
interface NumberMap {
    0: 1;
    1: 2;
    2: 3;
    3: 4;
    4: 5;
    5: 6;
    6: 7;
    7: 8;
    8: 9;
    9: 10;
    10: 11;
    11: 12;
    12: 13;
    13: 14;
    14: 15;
    15: 16;
    16: 17;
    17: 18;
    18: 19;
    19: 20;
    20: 21;
    21: 22;
    22: 23;
    23: 24;
    24: 25;
    25: 26;
    26: 27;
    27: 28;
    28: 29;
    29: 30;
    30: 31;
    31: 32;
    32: 33;
    33: 34;
    34: 35;
    35: 36;
    36: 37;
    37: 38;
    38: 39;
    39: 40;
    40: 41;
    41: 42;
    42: 43;
    43: 44;
    44: 45;
    45: 46;
    46: 47;
    47: 48;
    48: 49;
    49: 50;
    50: 51;
    51: 52;
    52: 53;
    53: 54;
    54: 55;
    55: 56;
    56: 57;
    57: 58;
    58: 59;
    59: 60;
    60: 61;
    61: 62;
    62: 63;
    63: 64;
    64: 65;
    65: 66;
    66: 67;
    67: 68;
    68: 69;
    69: 70;
    70: 71;
    71: 72;
    72: 73;
    73: 74;
    74: 75;
    75: 76;
    76: 77;
    77: 78;
    78: 79;
    79: 80;
    80: 81;
    81: 82;
    82: 83;
    83: 84;
    84: 85;
    85: 86;
    86: 87;
    87: 88;
    88: 89;
    89: 90;
    90: 91;
    91: 92;
    92: 93;
    93: 94;
    94: 95;
    95: 96;
    96: 97;
    97: 98;
    98: 99;
    99: 100;
    100: 101;
    101: 102;
    102: 103;
    103: 104;
    104: 105;
    105: 106;
    106: 107;
    107: 108;
    108: 109;
    109: 110;
    110: 111;
    111: 112;
    112: 113;
    113: 114;
    114: 115;
    115: 116;
    116: 117;
    117: 118;
    118: 119;
    119: 120;
    120: 121;
    121: 122;
    122: 123;
    123: 124;
    124: 125;
    125: 126;
    126: 127;
    127: 128;
    128: 129;
    129: 130;
    130: 131;
    131: 132;
    132: 133;
    133: 134;
    134: 135;
    135: 136;
    136: 137;
    137: 138;
    138: 139;
    139: 140;
    140: 141;
    141: 142;
    142: 143;
    143: 144;
    144: 145;
    145: 146;
    146: 147;
    147: 148;
    148: 149;
    149: 150;
    150: 151;
    151: 152;
    152: 153;
    153: 154;
    154: 155;
    155: 156;
    156: 157;
    157: 158;
    158: 159;
    159: 160;
    160: 161;
    161: 162;
    162: 163;
    163: 164;
    164: 165;
    165: 166;
    166: 167;
    167: 168;
    168: 169;
    169: 170;
    170: 171;
    171: 172;
    172: 173;
    173: 174;
    174: 175;
    175: 176;
    176: 177;
    177: 178;
    178: 179;
    179: 180;
    180: 181;
    181: 182;
    182: 183;
    183: 184;
    184: 185;
    185: 186;
    186: 187;
    187: 188;
    188: 189;
    189: 190;
    190: 191;
    191: 192;
    192: 193;
    193: 194;
    194: 195;
    195: 196;
    196: 197;
    197: 198;
    198: 199;
    199: 200;
    200: 201;
    201: 202;
    202: 203;
    203: 204;
    204: 205;
    205: 206;
    206: 207;
    207: 208;
    208: 209;
    209: 210;
    210: 211;
    211: 212;
    212: 213;
    213: 214;
    214: 215;
    215: 216;
    216: 217;
    217: 218;
    218: 219;
    219: 220;
    220: 221;
    221: 222;
    222: 223;
    223: 224;
    224: 225;
    225: 226;
    226: 227;
    227: 228;
    228: 229;
    229: 230;
    230: 231;
    231: 232;
    232: 233;
    233: 234;
    234: 235;
    235: 236;
    236: 237;
    237: 238;
    238: 239;
    239: 240;
    240: 241;
    241: 242;
    242: 243;
    243: 244;
    244: 245;
    245: 246;
    246: 247;
    247: 248;
    248: 249;
    249: 250;
    250: 251;
    251: 252;
    252: 253;
    253: 254;
    254: 255;
    255: 256;
    256: 257;
    257: 258;
    258: 259;
    259: 260;
    260: 261;
    261: 262;
    262: 263;
    263: 264;
    264: 265;
    265: 266;
    266: 267;
    267: 268;
    268: 269;
    269: 270;
    270: 271;
    271: 272;
    272: 273;
    273: 274;
    274: 275;
    275: 276;
    276: 277;
    277: 278;
    278: 279;
    279: 280;
    280: 281;
    281: 282;
    282: 283;
    283: 284;
    284: 285;
    285: 286;
    286: 287;
    287: 288;
    288: 289;
    289: 290;
    290: 291;
    291: 292;
    292: 293;
    293: 294;
    294: 295;
    295: 296;
    296: 297;
    297: 298;
    298: 299;
    299: 300;
    300: 301;
    301: 302;
    302: 303;
    303: 304;
    304: 305;
    305: 306;
    306: 307;
    307: 308;
    308: 309;
    309: 310;
    310: 311;
    311: 312;
    312: 313;
    313: 314;
    314: 315;
    315: 316;
    316: 317;
    317: 318;
    318: 319;
    319: 320;
    320: 321;
    321: 322;
    322: 323;
    323: 324;
    324: 325;
    325: 326;
    326: 327;
    327: 328;
    328: 329;
    329: 330;
    330: 331;
    331: 332;
    332: 333;
    333: 334;
    334: 335;
    335: 336;
    336: 337;
    337: 338;
    338: 339;
    339: 340;
    340: 341;
    341: 342;
    342: 343;
    343: 344;
    344: 345;
    345: 346;
    346: 347;
    347: 348;
    348: 349;
    349: 350;
    350: 351;
    351: 352;
    352: 353;
    353: 354;
    354: 355;
    355: 356;
    356: 357;
    357: 358;
    358: 359;
    359: 360;
    360: 361;
    361: 362;
    362: 363;
    363: 364;
    364: 365;
    365: 366;
    366: 367;
    367: 368;
    368: 369;
    369: 370;
    370: 371;
    371: 372;
    372: 373;
    373: 374;
    374: 375;
    375: 376;
    376: 377;
    377: 378;
    378: 379;
    379: 380;
    380: 381;
    381: 382;
    382: 383;
    383: 384;
    384: 385;
    385: 386;
    386: 387;
    387: 388;
    388: 389;
    389: 390;
    390: 391;
    391: 392;
    392: 393;
    393: 394;
    394: 395;
    395: 396;
    396: 397;
    397: 398;
    398: 399;
    399: 400;
    400: 401;
    401: 402;
    402: 403;
    403: 404;
    404: 405;
    405: 406;
    406: 407;
    407: 408;
    408: 409;
    409: 410;
    410: 411;
    411: 412;
    412: 413;
    413: 414;
    414: 415;
    415: 416;
    416: 417;
    417: 418;
    418: 419;
    419: 420;
    420: 421;
    421: 422;
    422: 423;
    423: 424;
    424: 425;
    425: 426;
    426: 427;
    427: 428;
    428: 429;
    429: 430;
    430: 431;
    431: 432;
    432: 433;
    433: 434;
    434: 435;
    435: 436;
    436: 437;
    437: 438;
    438: 439;
    439: 440;
    440: 441;
    441: 442;
    442: 443;
    443: 444;
    444: 445;
    445: 446;
    446: 447;
    447: 448;
    448: 449;
    449: 450;
    450: 451;
    451: 452;
    452: 453;
    453: 454;
    454: 455;
    455: 456;
    456: 457;
    457: 458;
    458: 459;
    459: 460;
    460: 461;
    461: 462;
    462: 463;
    463: 464;
    464: 465;
    465: 466;
    466: 467;
    467: 468;
    468: 469;
    469: 470;
    470: 471;
    471: 472;
    472: 473;
    473: 474;
    474: 475;
    475: 476;
    476: 477;
    477: 478;
    478: 479;
    479: 480;
    480: 481;
    481: 482;
    482: 483;
    483: 484;
    484: 485;
    485: 486;
    486: 487;
    487: 488;
    488: 489;
    489: 490;
    490: 491;
    491: 492;
    492: 493;
    493: 494;
    494: 495;
    495: 496;
    496: 497;
    497: 498;
    498: 499;
    499: 500;
    500: 501;
    501: 502;
    502: 503;
    503: 504;
    504: 505;
    505: 506;
    506: 507;
    507: 508;
    508: 509;
    509: 510;
    510: 511;
    511: 512;
    512: 513;
    513: 514;
    514: 515;
    515: 516;
    516: 517;
    517: 518;
    518: 519;
    519: 520;
    520: 521;
    521: 522;
    522: 523;
    523: 524;
    524: 525;
    525: 526;
    526: 527;
    527: 528;
    528: 529;
    529: 530;
    530: 531;
    531: 532;
    532: 533;
    533: 534;
    534: 535;
    535: 536;
    536: 537;
    537: 538;
    538: 539;
    539: 540;
    540: 541;
    541: 542;
    542: 543;
    543: 544;
    544: 545;
    545: 546;
    546: 547;
    547: 548;
    548: 549;
    549: 550;
    550: 551;
    551: 552;
    552: 553;
    553: 554;
    554: 555;
    555: 556;
    556: 557;
    557: 558;
    558: 559;
    559: 560;
    560: 561;
    561: 562;
    562: 563;
    563: 564;
    564: 565;
    565: 566;
    566: 567;
    567: 568;
    568: 569;
    569: 570;
    570: 571;
    571: 572;
    572: 573;
    573: 574;
    574: 575;
    575: 576;
    576: 577;
    577: 578;
    578: 579;
    579: 580;
    580: 581;
    581: 582;
    582: 583;
    583: 584;
    584: 585;
    585: 586;
    586: 587;
    587: 588;
    588: 589;
    589: 590;
    590: 591;
    591: 592;
    592: 593;
    593: 594;
    594: 595;
    595: 596;
    596: 597;
    597: 598;
    598: 599;
    599: 600;
    600: 601;
    601: 602;
    602: 603;
    603: 604;
    604: 605;
    605: 606;
    606: 607;
    607: 608;
    608: 609;
    609: 610;
    610: 611;
    611: 612;
    612: 613;
    613: 614;
    614: 615;
    615: 616;
    616: 617;
    617: 618;
    618: 619;
    619: 620;
    620: 621;
    621: 622;
    622: 623;
    623: 624;
    624: 625;
    625: 626;
    626: 627;
    627: 628;
    628: 629;
    629: 630;
    630: 631;
    631: 632;
    632: 633;
    633: 634;
    634: 635;
    635: 636;
    636: 637;
    637: 638;
    638: 639;
    639: 640;
    640: 641;
    641: 642;
    642: 643;
    643: 644;
    644: 645;
    645: 646;
    646: 647;
    647: 648;
    648: 649;
    649: 650;
    650: 651;
    651: 652;
    652: 653;
    653: 654;
    654: 655;
    655: 656;
    656: 657;
    657: 658;
    658: 659;
    659: 660;
    660: 661;
    661: 662;
    662: 663;
    663: 664;
    664: 665;
    665: 666;
    666: 667;
    667: 668;
    668: 669;
    669: 670;
    670: 671;
    671: 672;
    672: 673;
    673: 674;
    674: 675;
    675: 676;
    676: 677;
    677: 678;
    678: 679;
    679: 680;
    680: 681;
    681: 682;
    682: 683;
    683: 684;
    684: 685;
    685: 686;
    686: 687;
    687: 688;
    688: 689;
    689: 690;
    690: 691;
    691: 692;
    692: 693;
    693: 694;
    694: 695;
    695: 696;
    696: 697;
    697: 698;
    698: 699;
    699: 700;
    700: 701;
    701: 702;
    702: 703;
    703: 704;
    704: 705;
    705: 706;
    706: 707;
    707: 708;
    708: 709;
    709: 710;
    710: 711;
    711: 712;
    712: 713;
    713: 714;
    714: 715;
    715: 716;
    716: 717;
    717: 718;
    718: 719;
    719: 720;
    720: 721;
    721: 722;
    722: 723;
    723: 724;
    724: 725;
    725: 726;
    726: 727;
    727: 728;
    728: 729;
    729: 730;
    730: 731;
    731: 732;
    732: 733;
    733: 734;
    734: 735;
    735: 736;
    736: 737;
    737: 738;
    738: 739;
    739: 740;
    740: 741;
    741: 742;
    742: 743;
    743: 744;
    744: 745;
    745: 746;
    746: 747;
    747: 748;
    748: 749;
    749: 750;
    750: 751;
    751: 752;
    752: 753;
    753: 754;
    754: 755;
    755: 756;
    756: 757;
    757: 758;
    758: 759;
    759: 760;
    760: 761;
    761: 762;
    762: 763;
    763: 764;
    764: 765;
    765: 766;
    766: 767;
    767: 768;
    768: 769;
    769: 770;
    770: 771;
    771: 772;
    772: 773;
    773: 774;
    774: 775;
    775: 776;
    776: 777;
    777: 778;
    778: 779;
    779: 780;
    780: 781;
    781: 782;
    782: 783;
    783: 784;
    784: 785;
    785: 786;
    786: 787;
    787: 788;
    788: 789;
    789: 790;
    790: 791;
    791: 792;
    792: 793;
    793: 794;
    794: 795;
    795: 796;
    796: 797;
    797: 798;
    798: 799;
    799: 800;
    800: 801;
    801: 802;
    802: 803;
    803: 804;
    804: 805;
    805: 806;
    806: 807;
    807: 808;
    808: 809;
    809: 810;
    810: 811;
    811: 812;
    812: 813;
    813: 814;
    814: 815;
    815: 816;
    816: 817;
    817: 818;
    818: 819;
    819: 820;
    820: 821;
    821: 822;
    822: 823;
    823: 824;
    824: 825;
    825: 826;
    826: 827;
    827: 828;
    828: 829;
    829: 830;
    830: 831;
    831: 832;
    832: 833;
    833: 834;
    834: 835;
    835: 836;
    836: 837;
    837: 838;
    838: 839;
    839: 840;
    840: 841;
    841: 842;
    842: 843;
    843: 844;
    844: 845;
    845: 846;
    846: 847;
    847: 848;
    848: 849;
    849: 850;
    850: 851;
    851: 852;
    852: 853;
    853: 854;
    854: 855;
    855: 856;
    856: 857;
    857: 858;
    858: 859;
    859: 860;
    860: 861;
    861: 862;
    862: 863;
    863: 864;
    864: 865;
    865: 866;
    866: 867;
    867: 868;
    868: 869;
    869: 870;
    870: 871;
    871: 872;
    872: 873;
    873: 874;
    874: 875;
    875: 876;
    876: 877;
    877: 878;
    878: 879;
    879: 880;
    880: 881;
    881: 882;
    882: 883;
    883: 884;
    884: 885;
    885: 886;
    886: 887;
    887: 888;
    888: 889;
    889: 890;
    890: 891;
    891: 892;
    892: 893;
    893: 894;
    894: 895;
    895: 896;
    896: 897;
    897: 898;
    898: 899;
    899: 900;
    900: 901;
    901: 902;
    902: 903;
    903: 904;
    904: 905;
    905: 906;
    906: 907;
    907: 908;
    908: 909;
    909: 910;
    910: 911;
    911: 912;
    912: 913;
    913: 914;
    914: 915;
    915: 916;
    916: 917;
    917: 918;
    918: 919;
    919: 920;
    920: 921;
    921: 922;
    922: 923;
    923: 924;
    924: 925;
    925: 926;
    926: 927;
    927: 928;
    928: 929;
    929: 930;
    930: 931;
    931: 932;
    932: 933;
    933: 934;
    934: 935;
    935: 936;
    936: 937;
    937: 938;
    938: 939;
    939: 940;
    940: 941;
    941: 942;
    942: 943;
    943: 944;
    944: 945;
    945: 946;
    946: 947;
    947: 948;
    948: 949;
    949: 950;
    950: 951;
    951: 952;
    952: 953;
    953: 954;
    954: 955;
    955: 956;
    956: 957;
    957: 958;
    958: 959;
    959: 960;
    960: 961;
    961: 962;
    962: 963;
    963: 964;
    964: 965;
    965: 966;
    966: 967;
    967: 968;
    968: 969;
    969: 970;
    970: 971;
    971: 972;
    972: 973;
    973: 974;
    974: 975;
    975: 976;
    976: 977;
    977: 978;
    978: 979;
    979: 980;
    980: 981;
    981: 982;
    982: 983;
    983: 984;
    984: 985;
    985: 986;
    986: 987;
    987: 988;
    988: 989;
    989: 990;
    990: 991;
    991: 992;
    992: 993;
    993: 994;
    994: 995;
    995: 996;
    996: 997;
    997: 998;
    998: 999;
}

/**
 * Represents a range of positive integers from N to M (inclusive).
 * Both bounds must be positive integers.
 *
 * @template N Lower bound (must be positive integer)
 * @template M Upper bound (must be positive integer)
 *
 * @example
 * ```typescript
 * // Pagination example with a maximum of 100 items per page
 * interface PaginationParams {
 *   page: number;
 *   itemsPerPage: PositiveRange<1, 100>;
 * }
 *
 * async function fetchUsers({ page, itemsPerPage }: PaginationParams) {
 *   const offset = (page - 1) * itemsPerPage;
 *   return await db.users.findMany({
 *     skip: offset,
 *     take: itemsPerPage,
 *   });
 * }
 *
 * // Valid usage:
 * fetchUsers({ page: 1, itemsPerPage: 50 });  // ✅ OK
 *
 * // Type errors:
 * fetchUsers({ page: 1, itemsPerPage: 200 }); // ❌ Error: 200 exceeds maximum of 100
 * fetchUsers({ page: 1, itemsPerPage: 0 });   // ❌ Error: 0 is not in range
 * ```
 */
type PositiveRange<N extends number, M extends number> = [
    IsPositiveInteger<N>,
    IsPositiveInteger<M>
] extends [true, true] ? N extends M ? N : M extends N ? M : number extends N | M ? number : _BuildRange<N, M, []> : never;
/**
 * @hidden
 * @Internal helper to build range union recursively
 */
type _BuildRange<N extends number, M extends number, Acc extends number[], Current extends number = N> = Current extends M ? Current | Acc[number] : _BuildRange<N, M, [...Acc, Current], AddOne<Current>>;
/**
 * @hidden
 * @internal
 */
type AddOne<N extends number> = N extends keyof NumberMap ? NumberMap[N] : never;

type EmptyArray = [];
/**
 * Get the length of a given string
 * @example
 * ```ts
 * Strlen<'foo'>; // Result: 3
 * ```
 *
 * Can be used to create type constraints on string lengths:
 * ```ts
 * // Only allow strings of length 8-10 characters
 * type ValidPassword<T extends string> = Strlen<T> extends 8 | 9 | 10 ? T : never;
 *
 * // Function that only accepts valid password strings
 * function checkValidPassword<T extends string>(val: T & ValidPassword<T>) {
 *   console.log(val);
 * }
 *
 * // Works with string literals
 * const validPass = checkValidPassword('password123' as const); // OK
 * const invalidPass = checkValidPassword('short' as const); // Type error
 * ```
 */
type Strlen<S extends string, Arr extends unknown[] = EmptyArray> = S extends `${infer L}${infer R}` ? Strlen<R, [...Arr, L]> : Arr['length'];
/**
 * Check if a string is non-empty
 * @example
 * ```ts
 * export function filledString<S extends string>(s: FilledString<S>) {
 *   return s;
 * }
 * console.log(filledString('hello')); // Ok
 * console.log(filledString('')); // Error
 * ```
 */
type FilledString<T extends string = string> = Strlen<T> extends 0 ? Message<'must be non-empty string'> : T;
/**
 * Check if two strings S1 and S2 have the same length
 * @returns
 * ``true`` if they do, else ``false``
 */
type EqualStrlen<S1 extends string, S2 extends string> = Equals<Strlen<S1>, Strlen<S2>>;
/**
 * internal numeric tuple builder
 * converts a number literal to a tuple of that length for type-level math.
 * this is not the same as your Tuple<T> or SizedTuple<T, N> types;
 * it exists solely for numeric reasoning (e.g. comparisons like A <= B)
 */
type BuildTupleFromNumber<N extends number, T extends unknown[] = []> = T['length'] extends N ? T : BuildTupleFromNumber<N, [...T, unknown]>;
/**
 * type-level numeric comparator
 * evaluates to true if A <= B, else false
 */
type Lte<A extends number, B extends number> = BuildTupleFromNumber<B> extends [
    ...BuildTupleFromNumber<A>,
    ...unknown[]
] ? true : false;
/**
 * Constrain string to have length <= Max
 */
type StrMax<T extends string, Max extends number> = Lte<Strlen<T>, Max> extends true ? T : Message<`must be at most ${Max} characters long`>;
/**
 * Constrain string to have length >= Min
 */
type StrMin<T extends string, Min extends number> = Lte<Min, Strlen<T>> extends true ? T : Message<`must be at least ${Min} characters long`>;
/**
 * Constrain string to have Min <= length <= Max
 */
type StrBetween<T extends string, Min extends number, Max extends number> = Lte<Min, Strlen<T>> extends true ? Lte<Strlen<T>, Max> extends true ? T : Message<`must be at most ${Max} characters long`> : Message<`must be at least ${Min} characters long`>;

/**
 * EnforcedString
 *
 * Constructive constraint builder:
 *  - Prefix: must start with this
 *  - Contains: must contain this anywhere
 *  - Suffix: must end with this
 *
 * If a knob is the wide `string`, that knob imposes no constraint.
 * If all three are `string`, the result is plain `string`.
 *
 * @examples
 * type A = EnforcedString<'pk_'>;                 // `pk_${string}`
 * type B = EnforcedString<string, 'ABC'>;         // `${string}ABC${string}`
 * type C = EnforcedString<string, string, '.json'>; // `${string}.json`
 * type D = EnforcedString<'pk_', 'ABC', '.json'>; // `pk_${string}ABC${string}.json`
 * type E = EnforcedString<string, string, string>; // string
 */
type EnforcedString<Prefix extends string = string, Contains extends string = string, Suffix extends string = string> = Equals<Prefix, string> extends true ? Equals<Contains, string> extends true ? Equals<Suffix, string> extends true ? string : `${string}${Suffix}` : Equals<Suffix, string> extends true ? `${string}${Contains}${string}` : `${string}${Contains}${string}${Suffix}` : Equals<Contains, string> extends true ? Equals<Suffix, string> extends true ? `${Prefix}${string}` : `${Prefix}${string}${Suffix}` : Equals<Suffix, string> extends true ? `${Prefix}${string}${Contains}${string}` : `${Prefix}${string}${Contains}${string}${Suffix}`;

/**
 * Check if a string starts with another string
 * @example
 * ```ts
 * type Result = StringStartsWith<'hello world', 'hello'>; // Result: true
 * ```
 */
type StringStartsWith<T extends string, U extends string> = IfExtends<T, `${U}${string}`, true, false>;
/**
 * Check if a string ends with another string
 * @example
 * ```ts
 * type Result = StringEndsWith<'hello world', 'world'>; // Result: true
 * ```
 */
type StringEndsWith<T extends string, U extends string> = IfExtends<T, `${string}${U}`, true, false>;

/**
 * Capitalizes the first character of a string literal type while preserving the rest.
 * This is particularly useful when you need to transform string literal unions into
 * their capitalized counterparts.
 *
 * @template T The string literal type to capitalize
 *
 * @example
 * ```ts
 * type Category = "software" | "health" | "philosophy";
 * type Result = CapitalizeFirst<Category>; // "Software" | "Health" | "Philosophy"
 *
 * type Single = CapitalizeFirst<"hello">; // "Hello"
 * ```
 */
type CapitalizeFirst<T extends string> = T extends `${infer First}${infer Rest}` ? `${Capitalize<First>}${Rest}` : T;

/**
 * Represents a tuple.
 * @example
 * ````ts
 * Tuple<['a', 'b']>; // Result: ['a', 'b']
 * Tuple<string[]>; // Result: never
 */
type Tuple<T> = T extends readonly unknown[] ? number extends T['length'] ? never : T : never;
/**
 * Represents a tuple of size `N`, where `N` is a positive integer.
 * The tuple's length is exactly `N`, with each element of the tuple being of type `T`.
 *
 * @template T The type of the elements in the tuple.
 * @template N The desired length of the tuple.
 * @template Acc Accumulator type for recursive construction.
 *
 * @example
 * ```
 * SizedTuple<string, 3>; // Result: [string, string, string]
 * SizedTuple<number, 2>; // Result: [number, number]
 * SizedTuple<number, 0>; // Result: []
 * ```
 *
 * @see Tuple
 */
type SizedTuple<T, N extends Numeric, Acc extends T[] = []> = N extends PositiveInteger<infer M> ? Acc['length'] extends M ? Acc : SizedTuple<T, M, [T, ...Acc]> : never;
/**
 * Represents a non-empty array of elements of type `T`.
 * Ensures that the array has at least one item.
 *
 * @example
 * const valid: NonEmptyArray<number> = [1]; // ✅
 * const invalid: NonEmptyArray<number> = []; // ❌ Type error
 */
type NonEmptyArray<T> = [T, ...T[]];

/**
 * Represents a unique array type that filters out duplicate elements.
 * If a duplicate is encountered, it returns a tuple with an error message and the duplicate element.
 *
 * @template T The type of the elements in the array, which must be a readonly array.
 * @returns A readonly array of unique elements or a tuple indicating a duplicate.
 *
 * @example
 * ```
 * type Result1 = UniqueArray<[1, 2, 3, 1]>; // Result: ['Encountered duplicate element', 1]
 * type Result2 = UniqueArray<[1, 2, 3]>; // Result: [1, 2, 3]
 * type Result3 = UniqueArray<[]>; // Result: []
 * ```
 */
type UniqueArray<T extends readonly unknown[], Seen = never> = T extends readonly [infer Head, ...infer Tail] ? Head extends Seen ? ['Encountered duplicate element', Head] : readonly [Head, ...UniqueArray<Tail, Seen | Head>] : T;

/**
 * @returns `true` if `Arr` is an array that includes elements of type `T`, otherwise `false`.
 * An array of elements of type `T` is defined as `Arr` being a subtype of `T[]`.
 * @example
 * ```
 * IsArrayIncludeTypeof<Record<string, number>[], number> // false
 * IsArrayIncludeTypeof<string[], null | boolean> // false
 * ArrayIncludeTypeof<string[], string | boolean> // true
 * IsArrayIncludeTypeof<Record<string, number>[], Record<symbol, boolean>> // true,
 * ```
 */
type IsArrayIncludesTypeof<Arr, T> = IfExtends<Arr, T[], true, false>;

/**
 * Get the last element of an array
 * @example
 * ```ts
 * type Result1 = LastElement<[1, 2, 3]>; // Result: 3
 * type Result2 = LastElement<[]>; // Result: never
 * ```
 */
type LastElement<Arr extends unknown[]> = Arr extends [
    ...infer _Rest,
    infer Last
] ? Last : never;

/**
 * Get a set of properties from `T` whose type are not assignable to `P`.
 * @example
 * ````ts
 * type T = {
 *  foo: string,
 *  bar: bigint | boolean,
 *  baz: number,
 * }
 * OmitByType<T,true>; // Result: T
 * OmitByType<T,number>; // Result: { foo: string, bar: bigint | boolean }
 * ````
 */
type OmitByType<T, P> = {
    [K in Keys<T> as T[K] extends P ? never : K]: T[K];
};
/**
 * From ``T``, pick a set of properties whose type are assignable to ``P``.
 * @example
 * ````ts
 * type T = {
 *  foo: string,
 *  bar: bigint | boolean,
 *  baz: number,
 * }
 * PickByType<T,true>; // Result: {}
 * PickByType<T,number>; // Result: { baz: number }
 * ````
 */
type PickByType<T, P> = {
    [K in Keys<T> as T[K] extends P ? K : never]: T[K];
};
/**
 * From ``T``, pick a set of properties whose type excatly matches ``P``.
 * @example
 * ````ts
type OneLevelDeep = {
  foo: boolean;
  bar?: Numeric;
  baz: Nullable;
  fooBaz: bigint;
  bazFoo: string | boolean;
  seven: 7;
  aNum: number;
};
  type A = PickExactlyByType<OneLevelDeep, bigint>,
  // A results in:
    {
      fooBaz: bigint;
    },
  // Notice how it does not pick up seven
 type B = PickExactlyByType<OneLevelDeep, number>,
    {
      aNum: number;
    }
 * ````
 */
type PickExactlyByType<T, P> = {
    [K in Keys<T> as If<Equals<T[K], P>, K, never>]: T[K];
};

/**
 * A  type that recursively mutates all the proprties within a given object  type `T`.
 *
 * @example
 * ````ts
type Actual = {
  readonly a: () => 1;
  readonly x: string;
  readonly s: {
    readonly q: Nullable;
    readonly s: {
      readonly i: {
        readonly x: {
          readonly o: Maybe<Primitive>;
          readonly n: Falsy;
        };
        readonly e: 'foo';
      };
    };
  };
};

type Expected = {
  a: () => 1;
  x: string;
  s: {
    q: Nullable;
    s: {
      i: {
        x: {
          o: Maybe<Primitive>;
          n: Falsy;
        };
        e: 'foo';
      };
    };
  };
};
type T = DeepMutable<Actual>; // T Results in: Expected
 * ````
 */
type DeepMutable<T> = T extends UnknownFunction ? T : {
    -readonly [K in Keys<T>]: T[K] extends unknown ? DeepMutable<T[K]> : T[K];
};
/**
 * Checks if all the nested properties of a given object T are actually mutable.
 */
type IsDeepMutable<T> = T extends DeepMutable<T> ? true : false;
/**
 * Checks if all the nested properties of a given object T are actually immutable.
 */
type IsDeepImmutable<T> = T extends DeepImmutable<T> ? true : false;
/**
 * Check if all the properties of a given object (nested) are required
 * @returns
 * `true` if all the properties are, otherwise `false`
 */
type IsDeepRequired<T> = IfExtends<T, DeepRequired<T>, true, false>;
/**
 * Check if all the properties of a given object (nested) are non required
 * @returns
 * `true` if all the properties are, otherwise `false`
 */
type IsDeepNotRequired<T> = IfExtends<T, DeepNotRequired<T>, true, false>;
/**
 * A  type that recursively turns the proprties within a given object  type `T` immutable.
 * @example
 * ````ts
type Actual = {
  a: () => 1;
  x: string;
  s: {
    q: Nullable;
    s: {
      i: {
        x: {
          o: Maybe<Primitive>;
          n: Falsy;
        };
        e: 'foo';
      };
    };
  };
};

type Expected = {
  readonly a: () => 1;
  readonly x: string;
  readonly s: {
    readonly q: Nullable;
    readonly s: {
      readonly i: {
        readonly x: {
          readonly o: Maybe<Primitive>;
          readonly n: Falsy;
        };
        readonly e: 'foo';
      };
    };
  };
};
type T = DeepImmutable<Actual>; // T Results in: Expected
 * ````
 * */
type DeepImmutable<T> = T extends UnknownFunction ? T : {
    readonly [K in Keys<T>]: T[K] extends unknown ? DeepImmutable<T[K]> : T[K];
};
/**
 * Make all object properties required
 * @example
 * ```ts
type Expected = {
  a: () => 1;
  x: string;
  s: {
    q: Nullable;
    s: {
      i: {
        x: {
          o: Maybe<Primitive>;
          n: Falsy;
        };
        e: 'foo';
      };
    };
  };
};

type Actual = {
  a?: () => 1;
  x?: string;
  s?: {
    q?: Nullable;
    s?: {
      i?: {
        x?: {
          o?: Maybe<Primitive>;
          n?: Falsy;
        };
        e?: 'foo';
      };
    };
  };
};
type T = DeepRequired<Actual>; // Result: Expected
 * ```
 */
type DeepRequired<T> = T extends UnknownFunction ? T : {
    [K in Keys<T>]-?: IfExtends<T[K], unknown, DeepRequired<T[K]>, T[K]>;
};
/**
 * Why not call it ``DeepOptional``?
 * ``Optional<T>`` in this library `Optional` represents a type ``T`` that can be either ``T`` or ``null``. So creating
 * ``DeepOptional`` type would entail adding null to every property, which is not the intention here.
 *
 * ``DeepNotRequired<T>`` turns all required keys in a given object (nested) to non required one.
 * non required as in: marked with `?` operator
 * @example
 * ```ts
type Actual = {
  a: () => 1;
  x: string;
  s: {
    q: Nullable;
    s: {
      i: {
        x: {
          o: Maybe<Primitive>;
          n: Falsy;
        };
        e: 'foo';
      };
    };
  };
};

type Expected = {
  a?: () => 1;
  x?: string;
  s?: {
    q?: Nullable;
    s?: {
      i?: {
        x?: {
          o?: Maybe<Primitive>;
          n?: Falsy;
        };
        e?: 'foo';
      };
    };
  };
};
type T = DeepNotRequired<Actual>; // Result: Expected
 * ```
 */
type DeepNotRequired<T> = T extends UnknownFunction ? T : {
    [K in Keys<T>]+?: IfExtends<T[K], unknown, DeepNotRequired<T[K]>, T[K]>;
};

/**
 * Type that recursively omits specified nested properties from an object type.
 * @template T The input object type.
 * @template P A **string** literal representing the path of properties to omit (e.g., 'person.name.value').
 * @example
 * ```typescript
 * type T =
 *   a: {
 *     b: string;
 *     b2: {
 *       c: {
 *         d: number;
 *       };
 *     };
 *   };
 * }
 *
 * DeepOmit<T, 'a.b2.c'> // Results in: { a: { b: string; b2: {} } }
 * ```
 */
type DeepOmit<T, P extends string> = P extends `${infer K}.${infer R}` ? {
    [KT in Keys<T>]: KT extends K ? DeepOmit<T[KT], R> : T[KT];
} : Omit<T, P>;
/**
 * Deeply pick properties from a nested object type.
 * @template T The target object.
 * @template P A dot-separated string literal representing the path of properties to pick.
 * @example
 * type T = {
  one: string;
  two: {
    a: boolean;
    b: null;
    c: 'c' | 'C';
  };
  thee: number;
};
 * DeepPick<T, 'two.c'> // Results in:
{
    two: {
      c: 'c' | 'C';
    };
  }
 *
 */
type DeepPick<T extends Record<string, any>, // need to use `any` here for `T[K1]` inference
P extends string> = UnionToIntersection<P extends `${infer K}.${infer R}` ? {
    [K1 in K]: DeepPick<T[K1], R>;
} : P extends Keys<T> ? Pick<T, P> : never>;
/**
 * Generates all possible dot-separated key paths from a nested object type.
 * Returns a union of all valid key paths as string literals.
 *
 * @template T The object to extract paths from
 * @template Prev The accumulated path (used for recursion)
 *
 * @example
 * type Obj = {
 *   user: {
 *     profile: {
 *       name: string;
 *     };
 *   };
 *   age: number;
 * };
 *
 * type P = Paths<Obj>;
 * // Result:
 * // 'user'
 * // 'user.profile'
 * // 'user.profile.name'
 * // 'age'
 */
type Paths<T, Prev extends string = ''> = {
    [K in keyof T & string]: `${Prev}${K}` | (T[K] extends object ? Paths<T[K], `${Prev}${K}.`> : never);
}[keyof T & string];

/**
 * @hidden
 */
type _FlippableRecord = Record<string, string | number | boolean>;
/**
 * Constructs a new type that takes an object type `T` and returns a new object type where the keys of `T` become
 * the values and the values become the keys.
 *
 * @example
 * ```typescript
 * type Object1 = { name: 'John'; age: 30; city: 'New York' };
 * type Flipped1 = Flip<Object1>; // {'John': 'name', 30: 'age', 'New York': 'city'}
 *
 * type Object2 = { fruit: 'Apple'; color: 'Red'; price: 1.25 };
 * type Flipped2 = Flip<Object2>; // {'Apple': 'fruit', 'Red': 'color', 1.25: 'price'}
 *
 * type Object3 = { optionA: true; optionB: false };
 * type Flipped3 = Flip<Object3>; // {true: 'optionA', false: 'optionB'}
 * ```
 */
type Flip<T extends _FlippableRecord> = {
    [P in Keys<T> as StringifyPrimitive<T[P]>]: P;
};
/**
 * Constructs a new type by replacing keys of type `T` in object type `U` with corresponding keys from object type `Y`.
 * @template U The original object type.
 * @template T The type of keys to replace.
 * @template Y The object type containing replacement keys.
 *
 * @example
 * ```typescript
 * type Original = {
 *   bar: string;
 *   foo: number;
 *   fooBar: string;
 * };
 *
 * type Replacement = ReplaceKeys<Original, 'bar', { bar: number }>;
 *
 * // Result: { bar: number; foo: number; fooBar: string; }
 *
 * type AnotherReplacement = ReplaceKeys<Original, 'foo', { foo: boolean }>;
 *
 * // Result: { bar: string; foo: boolean; fooBar: string; }
 * ```
 */
type ReplaceKeys<U, T, Y> = {
    [K in Keys<U>]: IfExtends<K, T, K extends Keys<Y> ? Y[K] : never, U[K]>;
};
/**
 * @hidden
 */
type __Merge<T, S> = {
    [K in Keys<T> | Keys<S>]: K extends Keys<S> ? S[K] : T[K & Keys<T>];
};
/**
 * Copies all enumerable own properties from one target object
 * to a source array of objects.
 * @example
 * ````ts
 type T = Assign<{ a: 'd'; d: 'd' }, [{ a: 'a' }, { b: 'b' }, { c: 'c' }]>
 // Result:
 {
      a: 'a';
      b: 'b';
      c: 'c';
      d: 'd';
    }
 * ````
 */
type Assign<T extends Record<string, unknown>, Arr extends unknown[]> = Arr extends [infer S, ...infer E] ? Assign<S extends object ? __Merge<T, S> : T, E> : T;
/**
 * Get the common keys between two objects, if a key is found to be shared between both,
 * then the type of that key will take the first object's key type
 * @returns
 * An object that consist of what's common in both, else never
 * @example
 * ````ts
 CommonKeys<
      { d: 'first objects d'; x: 'also first objects x' },
      { d: 'd'; p: { b: 'b' }; x: { c: 'c' } }
    >
    // Results in { d: 'first objects d'; x: 'also first objects x' }
 * ````
 */
type PickCommonKeys<T extends Record<string, unknown>, U extends Record<string, unknown>> = Pick<T, Extract<Keys<T>, Keys<U>> & Extract<Keys<U>, Keys<T>>>;
/**
 * Omit the common keys between the the two objects,
 * @returns
 * An object that consist of what's unique in both, else never
 * @example
 * ````ts
 OmitCommonKeys<{ d: { d: 'a' }; p: { b: 'b' }; x: { c: 'c' } }, { d: 'd' }>
 // Result:
 {
      p: {
        b: 'b';
      };
      x: {
        c: 'c';
      };
    }

 OmitCommonKeys<
      { d: 'd'; k: 'k' },
      { d: 'd'; p: { b: 'b' }; x: { c: 'c' } }
    >
  // Result:
  { k: 'k' }
 * ````
 */
type OmitCommonKeys<T extends Record<string, unknown>, U extends Record<string, unknown>> = Pick<T, Exclude<Keys<T>, Keys<U>>>;
/**
 * Recursively transforms an object type T into a type where all properties are replaced with their corresponding primitive types.
 * @template T The object type to transform.
 * @returns A new object type with primitive types.
 *
 * @example
 * ```ts
 * type Actual = {
 *   a: 'a';
 *   b: 85;
 *   c: true;
 *   d: {
 *     e: 'xxxxxxxxxxx';
 *     f: 'eeeeeeeeeeeeeeeeee';
 *     g: {
 *       h: 1000000000000000;
 *       i: undefined;
 *       j: null;
 *     };
 *   };
 * };
 *
 * type Expected = {
 *   a: string;
 *   b: number;
 *   c: boolean;
 *   d: {
 *     e: string;
 *     f: string;
 *     g: {
 *       h: number;
 *       i: undefined;
 *       j: null;
 *     };
 *   };
 * };
 *
 * type Result = DeepToPrimitive<Actual>; // Result: Expected
 * ```
 */
type DeepToPrimitive<T> = {
    [K in Keys<T>]: T[K] extends object ? DeepToPrimitive<T[K]> : _FindPrimitive<T[K]>;
};
/**
 * @hidden
 */
type _FindPrimitive<T> = T extends string ? string : T extends symbol ? symbol : T extends boolean ? boolean : T extends null ? null : T extends number ? number : T extends bigint ? bigint : T extends undefined ? undefined : never;
/**
 * Infers a mapping from values to their corresponding keys within a given object type `T`.
 * The resulting type provides a reverse lookup, which allows to to retrieve the keys based on specific values.
 * @remarks
 * > This type only works with simple object types without nested structures or complex types.
 * It may not behave as expected with objects containing nested properties, union types, intersections, or other
 * advanced constructs.
 *
 * For example, given a simple object type `T`:
 *
 * ```typescript
 * type SimpleObjectType = {
 *   name: 'Zee';
 *   age: 29;
 *   city: 'Zion';
 * };
 *
 * type T =  KeysToValues<SimpleObjectType> // results in:
 *
 * {
 *   Zee : 'name';
 *   29: 'age';
 *   'Zion': 'city';
 * }
 * ```
 */
type KeysToValues<T extends Record<Keys<T>, Keys<any>>> = {
    [K in T[Keys<T>]]: {
        [K1 in Keys<T>]: T[K1] extends K ? K1 : never;
    }[Keys<T>];
};

/**
 * Retrieves the keys that are mutable from an object of  type T.
 * Basically keys that are not marked with the `readonly` modifier
 * @example
 * ```typescript
 *  type ExampleType = {
 *   a: number;
 *   readonly b: string;
 *   c: {
 *     a: string;
 *     d: { readonly x: Nullable; v: Maybe<Newable> };
 *   };
 * };
 *
 *  type MutableKeysOfExampleType = MutableKeys<ExampleType>;
 * // Result: 'a' | 'c'
 * ```
 */
type MutableKeys<T> = {
    [P in Keys<T>]: Equals<Pick<T, P>, Readonly<Pick<T, P>>> extends true ? never : P;
}[Keys<T>];
/**
 * Retrieves the keys that are immutable (readonly) from an object of  type T.
 * @example
 * ```typescript
 *  type ExampleType = {
 *   a: number;
 *   readonly b: string;
 *   c: {
 *     a: string;
 *     d: { readonly x: Nullable; v: Maybe<Newable> };
 *   };
 * };
 *
 *  type ImmutableKeysOfExampleType = ImmutableKeys<ExampleType>;
 * // Result: 'b'
 * ```
 */
type ImmutableKeys<T> = {
    [P in Keys<T>]: Equals<Pick<T, P>, Readonly<Pick<T, P>>> extends true ? P : never;
}[Keys<T>];

/**
 * Extracts truthy properties from an object type `T`.
 * @example
 * ````ts
type T = {
  name: string;
  age: number;
  hasCar: boolean;
  address?: string | null;
}
type R = TruthyProperties<T>;
// Result: { name: string; age: number; hasCar: boolean; }
 * ````
 */
type TruthyProperties<T> = Pick<T, {
    [K in Keys<T>]: IsTruthy<T[K]> extends true ? K : never;
}[Keys<T>]>;
/**
 * Extracts falsy properties from an object type `T`.
 * @example
 * ````ts
type T = {
  a: string;
  b: number;
  c: boolean;
  d?: string | null;
  e: 0;
  f: null;
};
type az = FalsyProperties<T>;
// Result: {
    e: 0;
    f: null;
}
 * ````
 */
type FalsyProperties<T> = Pick<T, {
    [K in Keys<T>]: IsFalsy<T[K]> extends true ? K : never;
}[Keys<T>]>;
/**
 * Get the literal names of keys that are methods in object type `T`
 * @example
 * ````ts
 Methods<{
      foo: () => void;
      bar: (a: any) => string;
      barBaz: string;
      bazBar: Numeric;
    }> // Result: 'foo' | 'bar'
 * ````
 */
type Methods<T extends object> = {
    [K in Keys<T>]-?: ExcludeNullable<T[K]> extends AnyFunction ? K : never;
}[Keys<T>];
/**
     * Get the literal names of keys that are propeties, basically anything that's not a method in object type `T`
     * @example
     * ````ts
     Properties<{
          barBaz: string;
          bazBar: Numeric;
          bar: () => number;
        }> // Result: 'barBaz' | 'bazBar'
     * ````
     */
type Properties<T extends object> = {
    [K in Keys<T>]-?: ExcludeNullable<T[K]> extends AnyFunction ? never : K;
}[Keys<T>];

declare const __s: unique symbol;
/**
 * This type represents a new unique type derived from an existing base type.
 * It defines a mechanism similar to Python's [`NewType`](https://docs.python.org/3/library/typing.html#newtype).
 * In TypeScript world it's refered to as 'Type Branding'.
 *
 * @template N The unique identifier for the new type.
 * @template T The base type of the new type.
 *
 * @example
 * type FooID = NewType<'FooID', string>;
 * type BarID = NewType<'BarID', string>;
 *
 * const fooId: FooID = 'foo123' as FooID;
 * const barId: BarID = 'bar456' as BarID;
 *
 * // Here's a potential bug:
 * const buggyFooBar = (foo: string, bar: string) => {};
 * buggyFooBar('bar456', 'foo123'); // this works but it's an undetected bug.
 *
 * // Bug mitigation:
 * const safeFooBar = (foo: FooID, bar: BarID) => {};
 * safeFooBar('bar456', 'foo123'); // TypeScript error: Argument of type 'string' is not assignable to parameter of type 'FooID'.
 */
type NewType<N, T> = T & {
    /**
     * Property `__s` is not intended for direct access nor modification.
     * @internal
     */ [__s]: N;
};

/**
 * `FilterBy<T, P>` filters keys from the object type `T` based on a specified predicate `P`.
 *
 * @remark
 * > This type performs a shallow filtering of keys within `T` and does not check deeply nested types
 * or complex structures within the object type.
 *
 * > It does not return the key as a whole object, it just returns the key itself
 * @example
 *
 * ```typescript
 * type T = {
 *   a: () => 1;
 *   x: string;
 *   s: {
 *     q: Nullable;
 *     s: {
 *       i: {
 *         x: {
 *           o: boolean;
 *           n: Falsy;
 *         };
 *         e: 'foo';
 *       };
 *     };
 *   };
 * };
 *
 * ```
 * ```typescript
 * type _ = FilterBy<T, 'a'>
 * ```
 * Results in the type `'a'`, which includes only the key `'a'` from `T`.
 * ```typescript
 * type _ = FilterBy<T, Falsy>
 * ```
 * Results in the type `never`, indicating that no keys in `T` match the type `Falsy`.
 *
 * ```typescript
 * type _ = FilterBy<T, string>
 * ```
 * Results in the type `'a' | 'x' | 's'`, which includes all top-level keys of `T`
 * that are of type `string`. It did not pick up on 'e' as it is nested down.
 */
type FilterBy<T, P> = {
    [K in Keys<T>]: K extends P ? K : never;
}[Keys<T>];
/**
 * Get a set of properties from `T` whose type exactly matches `P`.
 * @example
 * ````ts
type deep = {
        isActive: boolean;
        count?: number;
        description: string | null;
        details: {
          id: bigint;
          name: string;
          nested: {
            title: string;
            subtitle: string;
            moreDetails: {
              numberId: bigint;
            };
          };
        };
        additionalInfo: string | boolean;
      }
type A = OmitExactlyByTypeDeep<deep, bigint>
// A results in:
 {
      isActive: boolean;
      count?: number;
      description: string | null;
      details: {
        name: string;
        nested: {
          title: string;
          subtitle: string;
          moreDetails: EmptyObject;
        };
      };
      additionalInfo: string | boolean;
    }
 * ````
 */
type OmitExactlyByTypeDeep<T, P> = {
    [K in Keys<T> as IfEquals<T[K], P, never, K>]: OmitExactlyByTypeDeep<T[K], P>;
};
/**
 * `NotIncluded` is a utility type that represents a value that should not be included
 * in the final type. It is primarily used within the `Prune` type to exclude certain
 * properties from the resulting object type.
 *
 * @remarks
 * The `NotIncluded` type is typically used in conditional types to exclude specific
 * branches of the type structure. When a condition matches, `NotIncluded` is applied
 * to those properties that should be omitted from the final type structure.
 *
 * @example
 * ```ts
 * type MyType = IfEquals<'foo', 'bar', string, NotIncluded>; // Result: NotIncluded
 * ```
 *
 * In the context of the `Prune` type, `NotIncluded` helps in filtering out properties
 * from deeply nested structures where certain conditions do not hold.
 */
type NotIncluded = NewType<'NotIncluded', string>;
/**
 * `Prune<T, N = NotIncluded>` is a utility type that recursively removes properties of
 * type `N` (defaulting to `NotIncluded`) from the object type `T`. Useful
 * for filtering out unwanted or excluded properties in complex, deeply nested object
 * structures, where  you need to clean up or transform types where certain properties should be excluded based
 * on specific generic type conditions.
 * @example
 * Consider the following example where `Prune` is used to exclude properties marked as `NotIncluded`:
 * ```ts
 * type OrderData = Prune<
 *    UserOrderDetails<
 *      OrderStatus.DELIVERED,
 *      UserActionType.PLACE_ORDER,
 *      ProductType.PHYSICAL,
 *      PaymentMethod.PAYPAL
 *    >
 *  >;
 * ```
 * Where `UserOrderDetails` is defined as:
 * ```ts
 *
 * export enum OrderStatus {
 *   PENDING = 'PENDING',
 *   SHIPPED = 'SHIPPED',
 *   DELIVERED = 'DELIVERED',
 *   CANCELLED = 'CANCELLED',
 *   RETURNED = 'RETURNED',
 * }
 *
 * export enum PaymentMethod {
 *   CREDIT_CARD = 'CREDIT_CARD',
 *   PAYPAL = 'PAYPAL',
 *   BANK_TRANSFER = 'BANK_TRANSFER',
 *   CASH_ON_DELIVERY = 'CASH_ON_DELIVERY',
 *   CREDITS = 'CREDITS',
 * }
 *
 * export enum UserActionType {
 *   PLACE_ORDER = 'PLACE_ORDER',
 *   CANCEL_ORDER = 'CANCEL_ORDER',
 *   RETURN_ORDER = 'RETURN_ORDER',
 *   RATE_PRODUCT = 'RATE_PRODUCT',
 *   WRITE_REVIEW = 'WRITE_REVIEW',
 * }
 *
 * export enum ProductType {
 *   DIGITAL = 'DIGITAL',
 *   PHYSICAL = 'PHYSICAL',
 * }
 *
 * interface ShippingDetails {
 *   address: string;
 *   city: string;
 *   postalCode: string;
 *   country: string;
 *   deliveryDate: Maybe<string>;
 * }
 *
 * type ProductPricing<T extends ProductType> = {
 *   basePrice: number;
 *   discount: number;
 *   finalPrice: number;
 *   inCountryDiscount: IfEquals<T, ProductType.PHYSICAL, number, NotIncluded>;
 * };
 *
 * type ProductDetails<T extends ProductType> = {
 *   type: T;
 *   productId: string;
 *   productName: string;
 *   quantity: number;
 *   pricing: ProductPricing<T>;
 *   physicalDescription: IfEquals<
 *     T,
 *     ProductType.DIGITAL,
 *     {
 *       color: string;
 *       size: string;
 *     },
 *     NotIncluded
 *   >;
 * };
 *
 * type PaymentBreakdown = {
 *   baseAmount: number;
 *   tax: number;
 *   discount: number;
 *   finalAmount: number;
 * };
 *
 * interface PaymentDetails<PM extends PaymentMethod> {
 *   method: PM;
 *   transactionId: Maybe<string>;
 *   amountPaid: number;
 *   breakdown: IfEquals<PM, PaymentMethod.CREDITS, string, PaymentBreakdown>;
 * }
 *
 * type UserOrderDetails<
 *   OS extends OrderStatus,
 *   UAT extends UserActionType,
 *   PT extends ProductType,
 *   PM extends PaymentMethod,
 * > = {
 *   orderId: string;
 *   userId: string;
 *   products: ProductDetails<PT>[];
 *   orderStatus: OS;
 *   shipping: IfEquals<
 *     PT,
 *     ProductType.PHYSICAL,
 *     {
 *       details: IfEquals<
 *         OS,
 *         OrderStatus.SHIPPED | OrderStatus.DELIVERED,
 *         ShippingDetails,
 *         NotIncluded
 *       >;
 *       deliveredOn: IfEquals<OS, OrderStatus.DELIVERED, Date, NotIncluded>;
 *       returnedOn: IfEquals<OS, OrderStatus.RETURNED, Date, NotIncluded>;
 *     },
 *     NotIncluded
 *   >;
 *   payment: PaymentDetails<PM>;
 *   actions: {
 *     type: UAT;
 *     timestamp: number;
 *     metadata: IfEquals<
 *       UAT,
 *       | UserActionType.PLACE_ORDER
 *       | UserActionType.CANCEL_ORDER
 *       | UserActionType.RETURN_ORDER,
 *       {
 *         ipAddress: string;
 *         deviceType: string;
 *       },
 *       NotIncluded
 *     >;
 *   }[];
 * };
 * ```
 * Any property marked as `NotIncluded` will be excluded from the resulting `OrderData` type, not as `undefined` or `null`, but completely excluded as if it never existed on the type
 *
 * ```ts
 *  const testOrderData: OrderData = {
 *    orderStatus: OrderStatus.DELIVERED,
 *    actions: [
 *      {
 *        timestamp: 1663725600000,
 *        // Type 'UserActionType.RATE_PRODUCT' is not assignable to type 'UserActionType.PLACE_ORDER'.ts(2322)
 *        type: UserActionType.PLACE_ORDER,
 *        // Object literal may only specify known properties, and 'metadata' does not exist in type 'OmitExactlyByTypeDeep<{ type: UserActionType.PLACE_ORDER; timestamp: number; metadata: NotIncluded; }, NotIncluded>'.ts(2353)
 *        // metadata: {
 *        //   ipAddress: '127.0.0.1',
 *        //   deviceType: 'desktop',
 *        // },
 *      },
 *    ],
 *    orderId: '123',
 *    userId: 'abc',
 *    products: [
 *      {
 *        // Type 'ProdcutType.DIGITAL' is not assignable to type 'ProdcutType.PHYSICAL'.ts(2322)
 *        type: ProductType.PHYSICAL,
 *        productId: 'abc',
 *        productName: 'Test Product',
 *        quantity: 1,
 *        pricing: {
 *          basePrice: 10,
 *          discount: 0,
 *          finalPrice: 10,
 *          // If the product type is digital, the 'physicalDescription' property should be omitted
 *          // Object literal may only specify known properties, and 'inCountryDiscount' does not exist in type 'OmitExactlyByTypeDeep<ProductPricing<ProductType.DIGITAL>, NotIncluded>'.ts(2353)
 *          // physicalDescription: {
 *          //   color: 'Red',
 *          //   size: 'Large',
 *          // },
 *          inCountryDiscount: 87,
 *        },
 *      },
 *    ],
 *    payment: {
 *      amountPaid: 10,
 *      // If the PaymentMethod is CREDITS, the 'breakdown' property should be a string, no Breakdown object should exist
 *      // Type '{ baseAmount: number; tax: number; discount: number; finalAmount: number; }' is not assignable to type 'string'.
 *      breakdown: {
 *        baseAmount: 10,
 *        tax: 2,
 *        discount: 0,
 *        finalAmount: 12,
 *      },
 *      // Type 'PaymentMethod.BANK_TRANSFER' is not assignable to type 'PaymentMethod.PAYPAL'.ts(2322)
 *      // method: PaymentMethod.BANK_TRANSFER,
 *      method: PaymentMethod.PAYPAL,
 *      transactionId: '1234567890',
 *    },
 *    shipping: {
 *      deliveredOn: new Date(),
 *    },
 *  };
 * ```
 *
 * In this example, `Prune`  removes all properties within `UserOrderDetails`
 * that are marked with `NotIncluded`, resulting in a cleaned-up type structure.
 */
type Prune<T, N = NotIncluded> = OmitExactlyByTypeDeep<T, N>;

/**
 * Determines if two types match.
 * @template T1 The first  type to compare.
 * @template T2 The second  type to compare.
 * @template Expected A boolean literal indicating whether `T1` should match `T2`.
 * If you expect the types to match, set this to ``true``; if not, set it to false.
 * This utility will return a boolean that is ``true`` if your expectation was correct, otherwise false.
 * @example
```typescript
type ResultType = TestType<Type1, Type2, true>;
```
``TestType`` accepts three arguments: the types you're comparing (``Type1`` and ``Type2``) and a boolean (``true`` if you expected them to match, ``false`` otherwise). The resulting type will tell if your expectation is correct, ``true`` if it is, else ``false``.

You can use it however you want, maybe to test a type on the go, or,
test using a testing framework. Here's an example with [`vitest`](https://vitest.dev)

````ts
import type { Abs, TestType } from 'ts-roids';
import { test, expect , expectTypeOf} from 'vitest';

test('|-54| should be 54',() => {
  type ShouldPass = true;
  expectTypeOf<TestType<Abs<-54>, 54, true>>().toEqualTypeOf<ShouldPass>();
});
 * ````
 * */
type TestType<T1, T2, Expected extends boolean> = Equals<Equals<T1, T2>, Expected>;
/**
 * Checks if two types are exactly equal, same as `Equals` but with a more descriptive name.
 * @example
 *  type Result1 = Is<string, string>; // is true
 *  type Result2 = Is<number, string>; // is false
 *  type Result3 = Is<boolean | string, string | boolean>; // is true
 */
type Is<One, Two> = Equals<One, Two>;
/**
 * Checks if two types are not exactly equal.
 * @example
 *  type Result1 = IsNot<string, string>; // is false
 *  type Result2 = IsNot<number, string>; // is true
 *  type Result3 = IsNot<boolean | string, string | boolean>; // is false
 */
type IsNot<One, Two> = Not<Is<One, Two>>;

export type { Abs, And, AnyFunction, Assign, CapitalizeFirst, DeepAwaited, DeepImmutable, DeepMutable, DeepNotRequired, DeepOmit, DeepPick, DeepRequired, DeepToPrimitive, EitherOneOrMany, EmptyObject, EnforcedString, EqualStrlen, Equals, Even, ExcludeNull, ExcludeNullable, ExcludeUndefined, ExclusiveUnion, Extends, Falsy, FalsyProperties, FilledString, FilterBy, Flip, Float, If, IfEquals, IfExtends, ImmutableKeys, Integer, Is, IsAnyFunction, IsArray, IsArrayIncludesTypeof, IsBigInt, IsBoolean, IsDeepImmutable, IsDeepMutable, IsDeepNotRequired, IsDeepRequired, IsExactlyAny, IsExactlyBigInt, IsExactlyNumber, IsExactlyString, IsExactlySymbol, IsExactlyUnknown, IsFalsy, IsFloat, IsFunction, IsInteger, IsNegative, IsNegativeFloat, IsNegativeInteger, IsNever, IsNewable, IsNot, IsNullable, IsNumber, IsNumeric, IsObject, IsPositive, IsPositiveFloat, IsPositiveInteger, IsString, IsSymbol, IsTruthy, IsUnknown, Keys, KeysOfUnion, KeysToValues, LastElement, Maybe, MaybeUndefined, MaybeUnknown, Message, Methods, MutableKeys, Nand, NegativeFloat, NegativeFloatString, NegativeInteger, NegativeIntegerString, NewType, Newable, NonEmptyArray, NonRequiredKeys, Nor, Not, NotAssignableTo, NotIncluded, Nullable, Numeric, NumerifyString$2 as NumerifyString, Odd, OmitByType, OmitCommonKeys, OmitExactlyByTypeDeep, Optional, Or, PartialExcept, Paths, PickByType, PickCommonKeys, PickExactlyByType, PositiveFloat, PositiveFloatString, PositiveInteger, PositiveIntegerString, PositiveRange, Primitive, Properties, Prune, ReplaceKeys, RequiredKeys, Simplify, SizedTuple, StrBetween, StrMax, StrMin, StringEndsWith, StringStartsWith, StringifyPrimitive, Strlen, TestType, TruthyProperties, Tuple, UnionToIntersection, UnionToTuple, UniqueArray, UnknownFunction, Vals, Xand, Xnor, Xor };
