/** Forces a type to resolve its type definitions, to make it readable/debuggable. */ export type ResolveType = T extends object ? T extends infer O ? { [K in keyof O]: ResolveType } : never : T; /** Returns the type `true` iff X and Y are exactly equal */ export type TypeEqual = (() => T extends X ? 1 : 2) extends () => T extends Y ? 1 : 2 ? true : false; /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ export function assertTypeTrue<_ extends true>() {} /** `ReadonlyArray` of `ReadonlyArray`s. */ export type ROArrayArray = ReadonlyArray>; /** `ReadonlyArray` of `ReadonlyArray`s of `ReadonlyArray`s. */ export type ROArrayArrayArray = ReadonlyArray>>; /** * Deep version of the Readonly<> type, with support for tuples (up to length 7). * */ export type DeepReadonly = T extends [infer A] ? DeepReadonlyObject<[A]> : T extends [infer A, infer B] ? DeepReadonlyObject<[A, B]> : T extends [infer A, infer B, infer C] ? DeepReadonlyObject<[A, B, C]> : T extends [infer A, infer B, infer C, infer D] ? DeepReadonlyObject<[A, B, C, D]> : T extends [infer A, infer B, infer C, infer D, infer E] ? DeepReadonlyObject<[A, B, C, D, E]> : T extends [infer A, infer B, infer C, infer D, infer E, infer F] ? DeepReadonlyObject<[A, B, C, D, E, F]> : T extends [infer A, infer B, infer C, infer D, infer E, infer F, infer G] ? DeepReadonlyObject<[A, B, C, D, E, F, G]> : T extends Map ? ReadonlyMap, DeepReadonlyObject> : T extends Set ? ReadonlySet> : T extends Promise ? Promise> : T extends Primitive ? T : T extends (infer A)[] ? DeepReadonlyArray : DeepReadonlyObject; type Primitive = string | number | boolean | undefined | null | Function | symbol; type DeepReadonlyArray = ReadonlyArray>; type DeepReadonlyObject = { readonly [P in keyof T]: DeepReadonly }; /** * Computes the intersection of a set of types, given the union of those types. * * From: https://stackoverflow.com/a/56375136 */ export type UnionToIntersection = /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; /** "Type asserts" that `X` is a subtype of `Y`. */ type EnsureSubtype = X extends Y ? X : never; type TupleHeadOr = T extends readonly [infer H, ...(readonly unknown[])] ? H : Default; type TupleTailOr = T extends readonly [unknown, ...infer Tail] ? Tail : Default; type TypeOr = T extends undefined ? Default : T; /** * Zips a key tuple type and a value tuple type together into an object. * * @template Keys Keys of the resulting object. * @template Values Values of the resulting object. If a key corresponds to a `Values` member that * is undefined or past the end, it defaults to the corresponding `Defaults` member. * @template Defaults Default values. If a key corresponds to a `Defaults` member that is past the * end, the default falls back to `undefined`. */ export type ZipKeysWithValues< Keys extends readonly string[], Values extends readonly unknown[], Defaults extends readonly unknown[], > = // Keys extends readonly [infer KHead, ...infer KTail] ? { readonly [k in EnsureSubtype]: TypeOr< TupleHeadOr, TupleHeadOr >; } & ZipKeysWithValues< EnsureSubtype, TupleTailOr, TupleTailOr > : {}; // K exhausted