type Void<T> = T | void;
type Optional<T> = T | null | undefined;
type TernaryValue<T, U, V, W> = V extends W ? T : U;
type Nullable<T> = { [P in keyof T]: T[P] | null; };
type KeyOfType<T, U = any, V = any> = { [K in keyof T]: K extends U ? T[K] extends V ? K : never : never }[keyof T];
type MapOfType<T, U = any, V = any> = { [K in KeyOfType<T, U, V>]: K extends U ? T[K] extends V ? T[K] : never : never };
type PropertyValueSuffix<T extends string, U, V> = {
    [K in U as `${T}${string & K}`]?: V;
};

type Constructor<out T> = new(...args: any[]) => T;

type IteratorPredicate<in T, out U, V = ArrayLike<T>> = (item: T, index: number, array: V) => U;

type FunctionType<out T = unknown, in U = unknown> = (...args: U[]) => T;
type FunctionReturn<out T = unknown, in U = any> = (...args: U[]) => T;
type FunctionArgs<in T extends unknown[], out U = unknown> = (...args: T) => U;
type FunctionBind<in T, out U = void> = (this: T, ...args: unknown[]) => U;
type FunctionSelf<in T, out U> = (item: T, ...args: unknown[]) => U;
type FunctionSort<in T> = (a: T, b: T) => number;

type ArrayOf<T> = T | T[];
type BoxOf<T> = [T, T, T, T];
type MaybePromise<T, U, V = unknown> = TernaryValue<Promise<V>, V, T, U>;

type AnyObject = Record<string, unknown>;
type PlainObject = Record<string | number | symbol, unknown>;

type StandardMap<T = any> = Record<string, T>;
type StringMap = Record<string, string | undefined>;
type ObjectMap<T> = Record<string, T | undefined>;
type IterableMap<T> = Record<string, T>;
type RecursiveMap<T, N extends 4 | 3 | 2 | 1 = 2, U extends string | number | symbol = string> = N extends 1 ? Record<U, T | undefined> : RecursiveMap<Record<U, T | undefined>, N extends 4 ? 3 : N extends 3 ? 2 : 1>;