UNPKG

ox

Version:

Ethereum Standard Library

415 lines (375 loc) 8.99 kB
/** Combines members of an intersection into a readable type. */ // https://twitter.com/mattpocockuk/status/1622730173446557697?s=20&t=NdpAcmEFXY01xkqU3KO0Mg export type Compute<type> = { [key in keyof type]: type[key] } & unknown declare const symbol: unique symbol /** * Creates a branded type of `T` with the brand `U`. * * @example * ```ts * type Result = Branded<string, 'foo'> * // ^? type Result = string & { [symbol]: 'foo' } * ``` */ export type Branded<T, U> = T & { [symbol]: U } /** * Filters out all members of `T` that are not `P` * * @example * ```ts * type Result = Filter<['a', 'b', 'c'], 'b'> * // ^? type Result = ['a', 'c'] * ``` * * @internal */ export type Filter< T extends readonly unknown[], P, Acc extends readonly unknown[] = [], > = T extends readonly [infer F, ...infer Rest extends readonly unknown[]] ? [F] extends [P] ? Filter<Rest, P, [...Acc, F]> : Filter<Rest, P, Acc> : readonly [...Acc] /** * Checks if `T` can be narrowed further than `U` * * @example * ```ts * type Result = IsNarrowable<'foo', string> * // ^? true * ``` */ export type IsNarrowable<T, U> = IsNever< (T extends U ? true : false) & (U extends T ? false : true) > extends true ? false : true /** * Checks if `T` is `never` * * @example * ```ts * type Result = IsNever<never> * // ^? type Result = true * ``` */ export type IsNever<T> = [T] extends [never] ? true : false /** * Removes `readonly` from all properties of an object. * * @internal */ export type Mutable<type extends object> = { -readonly [key in keyof type]: type[key] } /** * Evaluates boolean "or" condition for `T` properties. * * * @example * ```ts * type Result = Or<[false, true, false]> * // ^? type Result = true * ``` * * @example * ```ts * type Result = Or<[false, false, false]> * // ^? type Result = false * ``` * * @internal */ export type Or<T extends readonly unknown[]> = T extends readonly [ infer Head, ...infer Tail, ] ? Head extends true ? true : Or<Tail> : false /** * Checks if `T` is `undefined` * * @example * ```ts * type Result = IsUndefined<undefined> * // ^? type Result = true * ``` * * @internal */ export type IsUndefined<T> = [undefined] extends [T] ? true : false /** * Checks if type `T` is the `unknown` type. * * @internal */ export type IsUnknown<T> = unknown extends T ? [T] extends [null] ? false : true : false /** @internal */ export type MaybePromise<T> = T | Promise<T> /** * Makes attributes on the type T required if required is true. * * @example * ```ts * MaybeRequired<{ a: string, b?: number }, true> * // { a: string, b: number } * * MaybeRequired<{ a: string, b?: number }, false> * // { a: string, b?: number } * ``` * * @internal */ export type MaybeRequired<T, required extends boolean> = required extends true ? ExactRequired<T> : T /** * Assigns the properties of U onto T. * * @example * ```ts * Assign<{ a: string, b: number }, { a: undefined, c: boolean }> * // { a: undefined, b: number, c: boolean } * ``` * * @internal */ export type Assign<T, U> = Assign_inner<T, U> & U /** @internal */ export type Assign_inner<T, U> = { [K in keyof T as K extends keyof U ? U[K] extends void ? never : K : K]: K extends keyof U ? U[K] : T[K] } /** * Constructs a type by excluding `undefined` from `T`. * * @example * ```ts * NoUndefined<string | undefined> * // string * ``` * * @internal */ export type NoUndefined<T> = T extends undefined ? never : T /** * Strict version of built-in Omit type * * @internal */ export type Omit<type, keys extends keyof type> = Pick< type, Exclude<keyof type, keys> > /** * Creates a type that is a partial of T, but with the required keys K. * * @example * ```ts * PartialBy<{ a: string, b: number }, 'a'> * // { a?: string, b: number } * ``` * * @internal */ export type PartialBy<T, K extends keyof T> = Omit<T, K> & ExactPartial<Pick<T, K>> export type RecursiveArray<T> = T | readonly RecursiveArray<T>[] /** * Creates a type that is T with the required keys K. * * @example * ```ts * RequiredBy<{ a?: string, b: number }, 'a'> * // { a: string, b: number } * ``` * * @internal */ export type RequiredBy<T, K extends keyof T> = Omit<T, K> & ExactRequired<Pick<T, K>> /** * Returns truthy if `array` contains `value`. * * @example * ```ts * Some<[1, 2, 3], 2> * // true * ``` * * @internal */ export type Some< array extends readonly unknown[], value, > = array extends readonly [value, ...unknown[]] ? true : array extends readonly [unknown, ...infer rest] ? Some<rest, value> : false /** * Prints custom error message * * @param messages - Error message * @returns Custom error message * * @example * ```ts * type Result = TypeErrorMessage<'Custom error message'> * // ^? type Result = ['Error: Custom error message'] * ``` */ export type TypeErrorMessage<messages extends string | string[]> = messages extends string ? [ // Surrounding with array to prevent `messages` from being widened to `string` `Error: ${messages}`, ] : { [key in keyof messages]: messages[key] extends infer message extends string ? `Error: ${message}` : never } /** @internal */ export type UnionToTuple< union, /// last = LastInUnion<union>, > = [union] extends [never] ? [] : [...UnionToTuple<Exclude<union, last>>, last] /** @internal */ export type LastInUnion<U> = UnionToIntersection< U extends unknown ? (x: U) => 0 : never > extends (x: infer l) => 0 ? l : never /** @internal */ export type UnionToIntersection<union> = ( union extends unknown ? (arg: union) => 0 : never ) extends (arg: infer i) => 0 ? i : never /** @internal */ export type IsUnion< union, /// union2 = union, > = union extends union2 ? ([union2] extends [union] ? false : true) : never /** @internal */ export type MaybePartial< type, enabled extends boolean | undefined, > = enabled extends true ? Compute<ExactPartial<type>> : type export type ExactPartial<type> = { [key in keyof type]?: type[key] | undefined } /** @internal */ export type ExactRequired<type> = { [key in keyof type]-?: Exclude<type[key], undefined> } export type OneOf< union extends object, fallback extends object | undefined = undefined, /// keys extends KeyofUnion<union> = KeyofUnion<union>, > = union extends infer item ? Compute< item & { [key in Exclude<keys, keyof item>]?: fallback extends object ? key extends keyof fallback ? fallback[key] : undefined : undefined } > : never /** @internal */ export type KeyofUnion<type> = type extends type ? keyof type : never /** @internal */ export type Undefined<type> = { [key in keyof type]?: undefined } /////////////////////////////////////////////////////////////////////////// // Loose types /** * Loose version of {@link Omit} * @internal */ export type LooseOmit<type, keys extends string> = Pick< type, Exclude<keyof type, keys> > /////////////////////////////////////////////////////////////////////////// // Union types /** @internal */ export type UnionCompute<type> = type extends object ? Compute<type> : type /** @internal */ export type UnionLooseOmit<type, keys extends string> = type extends any ? LooseOmit<type, keys> : never /** * Construct a type with the properties of union type T except for those in type K. * @example * ```ts * type Result = UnionOmit<{ a: string, b: number } | { a: string, b: undefined, c: number }, 'a'> * // { b: number } | { b: undefined, c: number } * ``` * * @internal */ export type UnionOmit<type, keys extends keyof type> = type extends any ? Omit<type, keys> : never /** * Construct a type with the properties of union type T except for those in type K. * @example * ```ts * type Result = UnionOmit<{ a: string, b: number } | { a: string, b: undefined, c: number }, 'a'> * // { b: number } | { b: undefined, c: number } * ``` * * @internal */ export type UnionPick<type, keys extends keyof type> = type extends any ? Pick<type, keys> : never /** * Creates a type that is a partial of T, but with the required keys K. * * @example * ```ts * PartialBy<{ a: string, b: number } | { a: string, b: undefined, c: number }, 'a'> * // { a?: string, b: number } | { a?: string, b: undefined, c: number } * ``` * * @internal */ export type UnionPartialBy<T, K extends keyof T> = T extends any ? PartialBy<T, K> : never /** * Creates a type that is T with the required keys K. * * @example * ```ts * RequiredBy<{ a?: string, b: number } | { a?: string, c?: number }, 'a'> * // { a: string, b: number } | { a: string, c?: number } * ``` * * @internal */ export type UnionRequiredBy<T, K extends keyof T> = T extends any ? RequiredBy<T, K> : never