// oxlint-disable no-explicit-any // ============================================================================ // Helpers // ============================================================================ /** * @example * ``` * // Expect: string | number | symbol * type Example1 = KeyOfBase * ``` */ export type KeyOfBase = keyof any /** * @description Cast type T to SafeT if possible; otherwise, return SafeT. * * @example * ``` * // Expect: number * type Example1 = Cast<42, number>; * // Expect: string * type Example2 = Cast<42, string>; * ``` */ export type Cast = T extends SafeT ? T : SafeT /** * @description Select a type based on a boolean condition. * * @example * ``` * // Expect: 1 * type Example1 = If * // Expect: 2 * type Example2 = If * ``` */ export type If = T extends true ? TRUE : FALSE /** * @description Return `T` if it extends `SafeT`, otherwise return `Catch`. * * @example * ``` * // Expect: 42 * type Example1 = Try<42, number, 0> * // Expect: 0 * type Example2 = Try<'x', number, 0> * ``` */ export type Try = T extends SafeT ? T : Catch /** * @description Get keys of an array/tuple or object, with numeric index support for tuples. * * @example * ``` * // Expect: 0 | 1 | number * type Example1 = Keys<[string, number]> * // Expect: 'a' | 'b' * type Example2 = Keys<{ a: 1; b: 2 }> * ``` */ export type Keys = A extends readonly any[] ? Exclude | number : keyof A /** * @description Check if two types are exactly equal. * * @example * ``` * // Expect: true * type Example1 = IsEqual<1, 1> * // Expect: false * type Example2 = IsEqual<1, number> * ``` * WARNING: https://github.com/ts-essentials/ts-essentials/blob/5aa1f264e77fb36bb3f673c49f00927c7c181a7f/lib/types.ts#L440 * * @see https://stackoverflow.com/a/52473108/1815209 with comments * @see https://github.com/millsp/ts-toolbelt/blob/319e551/sources/Any/Equals.ts#L15 */ export type IsEqual = (() => T extends A ? 1 : 2) extends () => T extends B ? 1 : 2 ? true : false /** * @description Select types based on exact type equality. * * @example * ``` * // Expect: 'yes' * type Example1 = IfEqual<1, 1, 'yes', 'no'> * // Expect: 'no' * type Example2 = IfEqual<1, number, 'yes', 'no'> * ``` */ export type IfEqual = (() => T extends X ? 1 : 2) extends () => T extends Y ? 1 : 2 ? TRUE : FALSE declare const InternalBrandId: unique symbol /** * @description Define nominal type of U based on type of T. Similar to Opaque types in Flow. * * @example * ``` * type USD = Brand * type EUR = Brand * * const tax = 5 as USD; * const usd = 10 as USD; * const eur = 10 as EUR; * * function gross(net: USD): USD { * return (net + tax) as USD; * } * * // Expect: No compile error * gross(usd); * // Expect: Compile error (Type '"EUR"' is not assignable to type '"USD"'.) * gross(eur); * ``` * * @see {@link https://github.com/piotrwitek/utility-types/blob/master/src/mapped-types.ts} */ export type Brand = T & { [InternalBrandId]: U } declare const InternalXPlaceholder: unique symbol /** * @description Provide an opaque placeholder type for generics. * * @example * ``` * // Expect: X * type Example1 = X * ``` */ export type X = typeof InternalXPlaceholder & {}