/**
 * Type guard for checking if a value is a key of the given enum.
 */
declare function isEnumValue<T extends Record<string, unknown>>(key: unknown, enumObject: T): key is T[keyof T];

/**
 * Type guard which checks if given value is inside an array.
 */
declare const isInArray: <T extends readonly any[]>(value: any, array: T) => value is T[number];

/**
 * Type guard for checking if an object value is of a specific type by checking if a given property exists.
 */
declare function isOfType<T>(value: any, property: keyof T): value is T;

/**
 * Forcibly type an array to have at least one element.
 */
type ArrayWithOneOrMore<T> = {
    0: T;
} & T[];

/**
 * Return a new record only with the keys whose values are assignable to the given type. If no keys are assignable to the given type, the resulting record must be empty.
 */
type ExtractRecord<T, U> = {
    [K in keyof T as T[K] extends U ? K : never]: T[K];
};

/**
 * Extracts the keys of a record whose values are assignable to the given type.
 */
type ExtractRecordKeys<T extends Record<any, any>, U> = keyof ExtractRecord<T, U>;

type MakeOptional<T, K extends string | keyof T> = K extends keyof T ? Omit<T, K> & Partial<Pick<T, K>> : T;

/**
 * Makes a type nullable or be undefined.
 */
type Maybe<T> = T | null | undefined;

/**
 * A type for an instantiable class.
 */
type Newable<T> = new (...args: any[]) => T;

/**
 * Allow a single value or an array of values.
 */
type OneOrMore<T> = T | T[];

type PromiseOr<T> = T | Promise<T>;

/**
 * Allows
 */
type ReadonlyOr<T> = T | Readonly<T>;

/**
 * Recursively makes all properties of an object optional.
 */
type RecursivePartial<T> = {
    [P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial<U>[] : T[P] extends object | undefined ? RecursivePartial<T[P]> : T[P];
};

/**
 * Recursively makes all properties of an object required.
 */
type RecursiveRequired<T> = {
    [P in keyof T]-?: T[P] extends (infer U)[] ? RecursiveRequired<U>[] : T[P] extends object | undefined ? RecursiveRequired<T[P]> : T[P];
};

type Replace<T, K extends keyof T, TReplace> = Pick<T, Exclude<keyof T, K>> & {
    [P in K]: TReplace;
};

/**
 * Makes all properties of an object optional except the ones specified.
 */
type RequireOnly<K, T extends keyof K> = Required<Pick<K, T>> & Partial<Omit<K, T>>;

/**
 * Resolves the type of given promise.
 */
type ResolvePromise<T extends Promise<any>> = T extends Promise<infer U> ? U : never;

/**
 * Inverts a map type so that the values become the keys and the keys become the values.
 */
type ReverseMap<T extends Record<keyof T, keyof any>> = {
    [P in T[keyof T]]: {
        [K in keyof T]: T[K] extends P ? K : never;
    }[keyof T];
};

/**
 * Get the values of a type
 */
type ValueOf<T extends Record<string, unknown>> = T[keyof T];

type MakeRequired<Type, Keys extends keyof Type> = Omit<Type, Keys> & Required<Pick<Type, Keys>>;

/**
 * Returns true if every element in the array satisfies the provided predicate.
 */
declare const asyncEvery: <A>(arr: A[], predicate: (value: A, index: number, array: A[]) => PromiseOr<boolean>) => Promise<boolean>;

/**
 * Returns true if some element in the array satisfies the provided predicate.
 */
declare const asyncSome: <A>(arr: A[], predicate: (value: A, index: number, array: A[]) => PromiseOr<boolean>) => Promise<boolean>;

/**
 * Returns true if given value is undefined.
 */
declare const isUndefined: (value: unknown) => value is undefined;

/**
 * Compares two objects and returns true if they are equal
 */
declare const objectIsEqual: (a: unknown, b: unknown) => boolean;

declare const partitionArray: <I>(array: I[] | null | undefined, predicate: (item: I) => boolean) => I[][];

/**
 * Removes keys and values from an object if predicate(value) returns true
 */
declare const removePropertiesWith: <T extends Record<string, unknown>>(object: T, predicate: (value: unknown) => boolean | Promise<boolean>) => Omit<T, keyof T>;

/**
 * Convert input to an array, if it's not already an array.
 */
declare const toArray: <T>(itemOrItems: OneOrMore<T>, separator?: string) => T[];

export { type ArrayWithOneOrMore, type ExtractRecord, type ExtractRecordKeys, type MakeOptional, type MakeRequired, type Maybe, type Newable, type OneOrMore, type PromiseOr, type ReadonlyOr, type RecursivePartial, type RecursiveRequired, type Replace, type RequireOnly, type ResolvePromise, type ReverseMap, type ValueOf, asyncEvery, asyncSome, isEnumValue, isInArray, isOfType, isUndefined, objectIsEqual, partitionArray, removePropertiesWith, toArray };
