import type { Nat } from "./Num"; import type { Add } from "./Num/Nat/Add"; import type { Repeat as RepeatString } from "./Str/Repeat"; import type { Repeat } from "./Tuple/Repeat"; import type { Eq } from "./helpers"; import type { Ord, Show } from "./typeclass"; /** * Mark a type as a construct type. * * It actually does nothing and is only used to make code more readable. */ export type Cons = T; /** * A type used to represent a type level function (aka. type lambda, or higher-kinded type (HKT)). * * It is type safe as long as the `Params` and `Return` are **correct**. * * Due to the **contravariant** nature of function inputs, `Params` are represented * using a function that takes `Params` as input. * * **⚠️ Warning:** Some utility types use `Params` and `Return` to provide type safety, * so **make sure** to use the **correct** `Params` and `Return` when defining a type level function. * * @example * ```typescript * interface PrependStringFn extends Fn<[string, string], string> { * def: ([start, s]: Args) => `${typeof start}${typeof s}`; * } * type R = $; * // ^?: "foobar" * ``` */ export interface Fn { readonly Params: (_: Params) => void; readonly Return: Return; } /** * The **unsafe** version of {@link Fn} (i.e. no type checking with `Params`). */ export interface FnW extends Fn {} /** * A shorthand for `Fn<[], R>`. * * @see {@link Fn} */ export interface Fn0 extends Fn<[], R> {} /** * A shorthand for `Fn<[A], R>`. * * @see {@link Fn} */ export interface Fn1 extends Fn<[A], R> {} /** * A shorthand for `Fn<[A, B], R>`. * * @see {@link Fn} */ export interface Fn2 extends Fn<[A, B], R> {} /** * A shorthand for `Fn<[A, B, C], R>`. * * @see {@link Fn} */ export interface Fn3 extends Fn<[A, B, C], R> {} /** * A shorthand for `Fn<[A, B, C, D], R>`. * * @see {@link Fn} */ export interface Fn4 extends Fn<[A, B, C, D], R> {} interface ApplyFnResolver extends GenericResolver<[Fn, readonly unknown[]], unknown> { on1_: ([f]: Args) => [[Readonly>], ReturnW]; on_1: ([, args]: Args) => typeof args extends unknown[] ? [[Fn], unknown] : never; on11: ([f, args]: Args) => [[], GenericReturnW]; on__r: ([, , r]: Args) => [Fn, readonly unknown[]]; } /** * [Fn] Apply a type level function with the given arguments. * * Sig: `(f: F, args: Params) => Return` */ interface ApplyFn extends GenericFn { def: ([f, args]: Args) => typeof f & { readonly Args: (_: _DeReadonly) => void; } extends { readonly def: (...args: never[]) => infer R } ? R : never; } export namespace Fn { /** * [Fn] Apply a type level function with the given arguments. * * Sig: `(f: F, args: Params) => Return` * * @example * ```typescript * type R1 = $, ["a", "b"]>; * // ^?: "ab" * type F = Fn.Apply; * type S = Sig; * // ^?: (x: readonly [string, string]) => number * type R2 = $; * // ^?: "foobar" * ``` */ export type Apply = PartialApply; } type Evaluate = { [K in keyof O]: O[K] }; /** * Get the arguments of a type level function and delay the evaluation of the arguments. * * It is normally used with `this` in HKT definition. * * @see {@link Fn} */ export type Args = Evaluate< F extends ( { readonly Args: ( _: infer Args extends Evaluate< F extends Fn ? [...AS, ...never[]] : [] >, ) => void; } ) ? Args : never >; /** * The **unsafe** version of `Args` (i.e. no type checking with `F`). * * @see {@link Args} */ export type ArgsW = Evaluate< F extends Fn ? F extends { readonly Args: (_: infer Args extends Readonly>) => void } ? Args : never : never >; /** * A shorthand for `Args[0]`. * * @see {@link Args} */ export type Arg0 = Args[0]; /** * The **unsafe** version of {@link Arg0} (i.e. no type checking with `F`). */ export type Arg0W = ArgsW[0]; /** * A shorthand for `Args[1]`. * * @see {@link Args} */ export type Arg1 = Args[1]; /** * The **unsafe** version of {@link Arg1} (i.e. no type checking with `F`). */ export type Arg1W = ArgsW[1]; /** * A shorthand for `Args[2]`. * * @see {@link Args} */ export type Arg2 = Args[2]; /** * The **unsafe** version of {@link Arg2} (i.e. no type checking with `F`). */ export type Arg2W = ArgsW[2]; /** * A shorthand for `Args[3]`. * * @see {@link Args} */ export type Arg3 = Args[3]; /** * The **unsafe** version of {@link Arg3} (i.e. no type checking with `F`). */ export type Arg3W = ArgsW[3]; /** * Get the length of the arguments of a type level function. */ export type ArgsLength = Args["length"]; /** * Get the parameters of a type level function. */ export type Params = F extends Fn ? A : []; /** * The **unsafe** version of {@link Params} (i.e. no type checking with `F`). */ export type ParamsW = F extends Fn ? A : []; /** * A shorthand for `Params[0]`. * * @see {@link Params} */ export type Param0 = Params[0]; /** * The **unsafe** version of {@link Param0} (i.e. no type checking with `F`). */ export type Param0W = ParamsW[0]; /** * A shorthand for `Params[1]`. * * @see {@link Params} */ export type Param1 = Params[1]; /** * The **unsafe** version of {@link Param1} (i.e. no type checking with `F`). */ export type Param1W = ParamsW[1]; /** * A shorthand for `Params[2]`. * * @see {@link Params} */ export type Param2 = Params[2]; /** * The **unsafe** version of {@link Param2} (i.e. no type checking with `F`). */ export type Param2W = ParamsW[2]; /** * A shorthand for `Params[3]`. * * @see {@link Params} */ export type Param3 = Params[3]; /** * The **unsafe** version of {@link Param3} (i.e. no type checking with `F`). */ export type Param3W = ParamsW[3]; /** * Get the length of the parameters of a type level function. * * @example * ```typescript * type R1 = ParamsLength; * // ^?: 1 * type R2 = ParamsLength; * // ^?: 2 * ``` */ export type ParamsLength = Params["length"]; /** * Get the return type of a type level function. */ export type Return = F["Return"]; /** * The **unsafe** version of {@link Return} (i.e. no type checking with `F`). */ export type ReturnW = F extends Fn ? F["Return"] : never; /** * Add readable names to all types in a tuple. */ type _NameAll = TS extends readonly [infer Head, ...infer Tail] ? [..._Name[0], ..._NameAll[1]>] : []; type _Name = Eq extends true ? [[s: T], "s"] : Eq extends true ? [[o: T], "o"] : [T] extends [Fn | ((...args: never) => unknown)] ? "g" extends Used ? [[h: T], "h"] : "f" extends Used ? [[g: T], "g"] : [[f: T], "f"] : Eq extends true ? [[ss: T], "ss"] : Eq extends true ? [[sss: T], "ss"] : Eq extends true ? [[os: T], "os"] : Eq extends true ? [[oo: T], "os"] : _IsNotFixedLengthArray extends true ? T extends readonly (infer U)[] ? [U] extends [string] ? [[ss: T], "ss"] : [U] extends [number | bigint] ? [[ns: T], "ns"] : [U] extends [boolean] ? [[bs: T], "bs"] : "xs" extends Used ? [[ys: T], "ys"] : [[xs: T], "xs"] : never : [T] extends [string] ? [[s: T], "s"] : [T] extends [number | bigint] ? "n" extends Used ? [[m: T], "m"] : [[n: T], "n"] : "y" extends Used ? [[z: T], "z"] : "x" extends Used ? [[y: T], "y"] : [[x: T], "x"]; type _IsNotFixedLengthArray = T extends readonly unknown[] ? number extends T["length"] ? true : false : false; /** * Get the signature of a type level function. * It should only be used for debugging purposes. */ export type Sig = _Sig; type _Sig = T extends Fn ? (...args: _NameAll<_SigAll>>) => _Sig> : T; type _SigAll = TS extends readonly [infer Head, ...infer Tail] ? [_Sig, ..._SigAll] : []; type _DeReadonly = { -readonly [K in keyof T]: T[K] }; /** * Use with {@link GenericFn} to define a generic type level function. */ export type GenericResolver = NOrBaseParams extends infer N extends Nat ? Fn<_DeReadonly, unknown>>, unknown> : NOrBaseParams extends infer BaseParams extends readonly unknown[] ? BaseParams["length"] extends 4 ? TypedGenericResolver4<_DeReadonly, BaseReturn> : BaseParams["length"] extends 3 ? TypedGenericResolver3<_DeReadonly, BaseReturn> : BaseParams["length"] extends 2 ? TypedGenericResolver2<_DeReadonly, BaseReturn> : BaseParams["length"] extends 1 ? TypedGenericResolver1<_DeReadonly, BaseReturn> : never : never; interface TypedGenericResolver4 extends Fn<[...BaseParams, BaseReturn]> { on____: () => [BaseParams, BaseReturn]; on1___: (_: any) => [[unknown, unknown, unknown], unknown]; on_1__: (_: any) => [[unknown, unknown, unknown], unknown]; on__1_: (_: any) => [[unknown, unknown, unknown], unknown]; on___1: (_: any) => [[unknown, unknown, unknown], unknown]; on11__: (_: any) => [[unknown, unknown], unknown]; on1_1_: (_: any) => [[unknown, unknown], unknown]; on1__1: (_: any) => [[unknown, unknown], unknown]; on_11_: (_: any) => [[unknown, unknown], unknown]; on_1_1: (_: any) => [[unknown, unknown], unknown]; on__11: (_: any) => [[unknown, unknown], unknown]; on111_: (_: any) => [[unknown], unknown]; on11_1: (_: any) => [[unknown], unknown]; on1_11: (_: any) => [[unknown], unknown]; on_111: (_: any) => [[unknown], unknown]; on1111: (_: any) => [[], unknown]; on____r: (_: any) => BaseParams; on1___r: (_: any) => [BaseParams[1], BaseParams[2], BaseParams[3]]; on_1__r: (_: any) => [BaseParams[0], BaseParams[2], BaseParams[3]]; on__1_r: (_: any) => [BaseParams[0], BaseParams[1], BaseParams[3]]; on___1r: (_: any) => [BaseParams[0], BaseParams[1], BaseParams[2]]; on11__r: (_: any) => [BaseParams[2], BaseParams[3]]; on1_1_r: (_: any) => [BaseParams[1], BaseParams[3]]; on1__1r: (_: any) => [BaseParams[1], BaseParams[2]]; on_11_r: (_: any) => [BaseParams[0], BaseParams[3]]; on_1_1r: (_: any) => [BaseParams[0], BaseParams[2]]; on__11r: (_: any) => [BaseParams[0], BaseParams[1]]; on111_r: (_: any) => [BaseParams[3]]; on11_1r: (_: any) => [BaseParams[2]]; on1_11r: (_: any) => [BaseParams[1]]; on_111r: (_: any) => [BaseParams[0]]; } interface TypedGenericResolver3 extends Fn<[...BaseParams, BaseReturn]> { on___: () => [BaseParams, BaseReturn]; on1__: (_: any) => [[unknown, unknown], unknown]; on_1_: (_: any) => [[unknown, unknown], unknown]; on__1: (_: any) => [[unknown, unknown], unknown]; on11_: (_: any) => [[unknown], unknown]; on1_1: (_: any) => [[unknown], unknown]; on_11: (_: any) => [[unknown], unknown]; on111: (_: any) => [[], unknown]; on___r: (_: any) => BaseParams; on1__r: (_: any) => [BaseParams[1], BaseParams[2]]; on_1_r: (_: any) => [BaseParams[0], BaseParams[2]]; on__1r: (_: any) => [BaseParams[0], BaseParams[1]]; on11_r: (_: any) => [BaseParams[2]]; on1_1r: (_: any) => [BaseParams[1]]; on_11r: (_: any) => [BaseParams[0]]; } interface TypedGenericResolver2 extends Fn<[...BaseParams, BaseReturn]> { on__: () => [BaseParams, BaseReturn]; on1_: (_: any) => [[unknown], unknown]; on_1: (_: any) => [[unknown], unknown]; on11: (_: any) => [[], unknown]; on__r: (_: any) => BaseParams; on1_r: (_: any) => [BaseParams[1]]; on_1r: (_: any) => [BaseParams[0]]; } interface TypedGenericResolver1 extends Fn<[...BaseParams, BaseReturn]> { on_: () => [BaseParams, BaseReturn]; on1: (_: any) => [[], unknown]; on_r: (_: any) => BaseParams; } /** * Apply a {@link GenericResolver} by mask and arguments. * * Type safety is **not guaranteed**. */ export type ApplyGenericResolver< F extends Fn, Mask extends string, Args extends readonly unknown[], > = F & { readonly Args: (_: Args) => void } extends { readonly [P in `on${Mask}`]: (...args: never[]) => infer R; } ? R : void; type PartialApplyGenericResolverBy1 = Resolver extends Fn4 ? PartialApplyGenericResolver3by1 : Resolver extends Fn3 ? PartialApplyGenericResolver2by1 : never; interface PartialApplyGenericResolver3by1 extends GenericResolver<2> { on__: () => ApplyGenericResolver, Arg1, never]>; on1_: () => ApplyGenericResolver, never, never]>; on_1: () => ApplyGenericResolver, never]>; on11: () => ApplyGenericResolver, Arg1, never]>; on__r: () => ApplyGenericResolver]>; on1_r: () => ApplyGenericResolver, never, Arg2]>; on_1r: () => ApplyGenericResolver, Arg2]>; } interface PartialApplyGenericResolver3by2 extends GenericResolver<2> { on__: () => ApplyGenericResolver; on1_: () => ApplyGenericResolver, A2, never, never]>; on_1: () => ApplyGenericResolver, never]>; on11: () => ApplyGenericResolver, A2, Arg1, never]>; on__r: () => ApplyGenericResolver]>; on1_r: () => ApplyGenericResolver, A2, never, Arg2]>; on_1r: () => ApplyGenericResolver, Arg2]>; } interface PartialApplyGenericResolver3by3 extends GenericResolver<2> { on__: () => ApplyGenericResolver; on1_: () => ApplyGenericResolver, never, A3, never]>; on_1: () => ApplyGenericResolver, A3, never]>; on11: () => ApplyGenericResolver, Arg1, A3, never]>; on__r: () => ApplyGenericResolver]>; on1_r: () => ApplyGenericResolver, never, A3, Arg2]>; on_1r: () => ApplyGenericResolver, A3, Arg2]>; } interface PartialApplyGenericResolver3by12 extends GenericResolver<1> { on_: () => ApplyGenericResolver; on1: () => ApplyGenericResolver]>; on_r: () => ApplyGenericResolver]>; } interface PartialApplyGenericResolver3by13 extends GenericResolver<1> { on_: () => ApplyGenericResolver, A3]>; on1: () => ApplyGenericResolver, A3]>; on_r: () => ApplyGenericResolver]>; } interface PartialApplyGenericResolver3by23 extends GenericResolver<1> { on_: () => ApplyGenericResolver, A2, A3]>; on1: () => ApplyGenericResolver, A2, A3]>; on_r: () => ApplyGenericResolver]>; } interface PartialApplyGenericResolver2by1 extends GenericResolver<1> { on_: () => ApplyGenericResolver]>; on1: () => ApplyGenericResolver]>; on_r: () => ApplyGenericResolver]>; } interface PartialApplyGenericResolver2by2 extends GenericResolver<1> { on_: () => ApplyGenericResolver, A2]>; on1: () => ApplyGenericResolver, A2]>; on_r: () => ApplyGenericResolver]>; } type PartialApplyGenericResolver< Resolver extends Fn, Mask, AppliedArgs extends readonly unknown[], > = Mask extends "1__" ? PartialApplyGenericResolver3by1 : Mask extends "_1_" ? PartialApplyGenericResolver3by2 : Mask extends "__1" ? PartialApplyGenericResolver3by3 : Mask extends "11_" ? PartialApplyGenericResolver3by12 : Mask extends "1_1" ? PartialApplyGenericResolver3by13 : Mask extends "_11" ? PartialApplyGenericResolver3by23 : Mask extends "1_" ? PartialApplyGenericResolver2by1 : Mask extends "_1" ? PartialApplyGenericResolver2by2 : never; /** * Curry a {@link GenericResolver}. */ type CurryGenericResolver = Resolver extends Fn<[never, never, never, never, never]> ? CurryGenericResolver4 : Resolver extends Fn4 ? CurryGenericResolver3 : Resolver extends Fn3 ? CurryGenericResolver2 : Resolver extends Fn2 ? Resolver : never; interface CurryGenericResolver4> extends GenericResolver<1> { on_: () => ApplyGenericResolver extends ( readonly [readonly [infer A1, infer A2, infer A3, infer A4], infer R] ) ? [[A1], Fn1>>] : never; on1: () => ApplyGenericResolver< Resolver, "1___", [Arg0, never, never, never, never] > extends readonly [readonly [infer A2, infer A3, infer A4], infer R] ? [[A2], Fn1>] : never; on_r: ([, r]: Args) => typeof r extends Fn1>> ? [A, B, C, R] extends [never, never, never, never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1, unknown, unknown, unknown], unknown] ) ? [A1] : never : [A, B, C] extends [never, never, never] ? ApplyGenericResolver extends ( readonly [infer A1, unknown, unknown, unknown] ) ? [A1] : never : [A, B, R] extends [never, never, never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1, unknown, unknown, unknown], unknown] ) ? [A1] : never : [A, C, R] extends [never, never, never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1, unknown, unknown, unknown], unknown] ) ? [A1] : never : [B, C, R] extends [never, never, never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1, unknown, unknown, unknown], unknown] ) ? [A1] : never : [A, B] extends [never, never] ? ApplyGenericResolver extends ( readonly [infer A1, unknown, unknown] ) ? [A1] : never : [A, C] extends [never, never] ? ApplyGenericResolver extends ( readonly [infer A1, unknown, unknown] ) ? [A1] : never : [A, R] extends [never, never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1, unknown], unknown] ) ? [A1] : never : [B, C] extends [never, never] ? ApplyGenericResolver extends ( readonly [infer A1, unknown, unknown] ) ? [A1] : never : [B, R] extends [never, never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1, unknown], unknown] ) ? [A1] : never : [C, R] extends [never, never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1, unknown], unknown] ) ? [A1] : never : [A] extends [never] ? ApplyGenericResolver extends ( readonly [infer A1, unknown] ) ? [A1] : never : [B] extends [never] ? ApplyGenericResolver extends ( readonly [infer A1, unknown] ) ? [A1] : never : [C] extends [never] ? ApplyGenericResolver extends ( readonly [infer A1, unknown] ) ? [A1] : never : [R] extends [never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1], unknown] ) ? [A1] : never : ApplyGenericResolver extends readonly [infer A1] ? [A1] : never : never; } interface CurryGenericResolver3 extends GenericResolver<1> { on_: () => ApplyGenericResolver extends ( readonly [readonly [infer A1, infer A2, infer A3], infer R] ) ? [[A1], Fn1>] : never; on1: () => ApplyGenericResolver, never, never, never]> extends ( readonly [readonly [infer A2, infer A3], infer R] ) ? [[A2], Fn1] : never; on_r: ([, r]: Args) => typeof r extends Fn1> ? [A, B, R] extends [never, never, never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1, unknown, unknown], unknown] ) ? [A1] : never : [A, B] extends [never, never] ? ApplyGenericResolver extends ( readonly [infer A1, unknown, unknown] ) ? [A1] : never : [A, R] extends [never, never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1, unknown], unknown] ) ? [A1] : never : [B, R] extends [never, never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1, unknown], unknown] ) ? [A1] : never : [A] extends [never] ? ApplyGenericResolver extends ( readonly [infer A1, unknown] ) ? [A1] : never : [B] extends [never] ? ApplyGenericResolver extends ( readonly [infer A1, unknown] ) ? [A1] : never : [R] extends [never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1], unknown] ) ? [A1] : never : ApplyGenericResolver extends readonly [infer A1] ? [A1] : never : never; } interface CurryGenericResolver2 extends GenericResolver<1> { on_: () => ApplyGenericResolver extends ( readonly [readonly [infer A1, infer A2], infer R] ) ? [[A1], Fn1 & { readonly GenericResolver: PartialApplyGenericResolver2by1 }] : never; on1: ([a1]: Args) => ApplyGenericResolver< Resolver, "1_", [typeof a1, never, never] > extends readonly [readonly [infer A2], infer R] ? [ [], Fn1 & { readonly GenericResolver: PartialApplyGenericResolver2by1; }, ] : never; on_r: ([, r]: Args) => typeof r extends Fn1 ? [A] extends [never] ? ApplyGenericResolver extends ( readonly [infer A1, unknown] ) ? [A1] : never : [R] extends [never] ? ApplyGenericResolver extends ( readonly [readonly [infer A1], unknown] ) ? [A1] : never : ApplyGenericResolver, ReturnW]> : never; } type ResolveGenericSignature< Resolver extends Fn, Mask extends string, PinnedArgs extends readonly unknown[], > = ApplyGenericResolver, never]>; /** * A generic type level function. * * @example * ```typescript * import type { Args, Ask, Broaden, Flow, GenericFn, GenericResolver, PartialApply, Sig } from "rivo"; * * // Say you want to define a type level function `Append` with signature * // `(x: T, xs: T[]) => T[]`. * * // Define a resolver to represent the signature first * interface Resolver extends GenericResolver<[unknown, unknown[]], unknown[]> { * // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * // The base signature when no arguments are applied (`(x: unknown, xs: unknown[]) => unknown[]`) * * // ↙ How the resolver refines the function signature when the first argument is applied * // Here, `1_` means the first argument is applied (the corresponding char is `1`), * // and the second argument is not applied (the corresponding char is `_`). * // The rest will follow the same pattern, e.g., `on_1` means when the first argument is not * // applied and the second argument is applied, `on11` means when both arguments are applied. * on1_: ([x]: Args) => [[Broaden[]], Broaden[]]; * // A `GenericResolver` can be seen as sort of type-level function, where it takes a tuple of * // already known parameter types and return type, and refines the signature based on them. * // Here, for `on1_`, we know the first parameter type, so the input tuple would be * // `[, never, never]` (because the second parameter type and the return type are not * // known yet). * // Let’s think about how can we refine the signature based on the input tuple, and in this * // case, the only known parameter type is ``. Take a back look at the expected * // signature `(x: T, xs: T[]) => T[]`, since we already know the type of `x`, we can infer * // the type of `T`, so the type of `xs` would be `[]`, and the return type would be * // `[]` as well. We should write them in the form of * // `[[...], ]`, so we get `[[(typeof x)[]], (typeof x)[]]` * // here — But actually we’ll get precise types like `42` instead of `number` sometimes, and in * // such case the inferred signature would be `(x: 42, xs: 42[]) => 42[]` if we just use * // `[[(typeof x)[]], (typeof x)[]]`, so here we use `Broaden` to get a more general type. The * // use of `Broaden` is not a must, and sometimes you may actually want a precise type, in such * // case you should just use `typeof x` directly. * * // ↙ Things are similar for the rest of the methods, take a look and try to understand them. * on_1: ([, xs]: Args) => [[Broaden<(typeof xs)[number]>], Broaden<(typeof xs)[number]>[]]; * // ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * // ↑ Inferred type of `x` Inferred return type * // Input tuple: `[never, , never]` * * // ↙ When both parameter types are known, we left the `[...]` tuple empty * // (i.e. `[]`), and only need to return the inferred return type. * on11: ([x, xs]: Args) => [[], (typeof x | (typeof xs)[number])[]]; * * // ↙ Things become a little special when we want to back infer the parameter types from the * // return type — if you wonder why we need this, think about a function that requires another * // function that returns a specific type as a parameter, and in such case we can refine the * // parameter types based on the return type of the function. * // We use a `r` postfix here to indicate the return type is known, and the `__` in `__r` * // means both parameter types are not known. * // We do not use the form `[[...], ]` here, because we * // already know the return type, so we just need to return the inferred parameter types (i.e. * // `[...]`). * on__r: ([, , r]: Args) => [(typeof r)[number], typeof r]; * // You can see here we choose not to use `Broaden`, because usually the known return type is * // not a precise type, so it is not necessary to use `Broaden` here. * * // ↙ Define other back inference methods when some parameter types are known. * on1_r: ([x, , r]: Args) => [typeof r]; * * on_1r: ([, xs, r]: Args) => [(typeof r)[number]]; * * // `on11r` is apparently not needed, because since we already know all parameter types and the * // return type, there is no need to back infer any parameter types. * // on11r: Not needed * } * * // Then define the type level function with its `GenericResolver` * interface AppendFn extends GenericFn { * def: ([x, xs]: Args) => [...typeof xs, typeof x]; * } * * type S1 = Sig; * // ^?: (x: unknown, xs: unknown[]) => unknown[] * // ↙ `on1_` is used here to refine the signature * type S2 = Sig>; * // ^?: (ns: number[]) => number[] * // ↙ `on_1` is used here to refine the signature * type S3 = Sig>; * // ^?: (s: string) => string[] * * type AppendWithFn = PartialApply; * // ↙ `on11` is used here to refine the signature * type S4 = Sig, AppendWithFn<42>>>; * // ^?: (ns: number[]) => number[] * // ↙ `on1_` is used here to give the type error (the inferred signature of `AppendWithFn<"foo">` is * // `(ss: string[]) => string[]`, but we expect a function that takes `number[]` as the parameter) * type Wrong = Flow, AppendWithFn<"foo">>; * // ~~~~~~~~~~~~~~~~~~~ * // ... Type 'number' is not assignable to type 'string'. * ``` * * @see {@link GenericResolver} */ export type GenericFn = [ResolverOrParams] extends [infer Params extends unknown[]] ? Fn & { readonly GenericResolver: Fn< [..._DeReadonly>, never], unknown >; } : [ResolverOrParams] extends [infer Resolver extends Fn] ? ResolveGenericSignature< Resolver, RepeatString>["length"], "_">, [] > extends [infer Args extends unknown[], infer Return] ? Fn<_DeReadonly, Return> & { readonly GenericResolver: Resolver } : never : never; /** * Specialize a generic type level function with the given arguments. */ export interface Specialize< F extends Fn & { readonly GenericResolver: Fn }, PinnedParams extends Mask extends "default" ? LegalPinnedArgsDefault : LegalPinnedArgs, Mask extends string = "default", > extends Fn< ResolveGenericSignature< F["GenericResolver"], Mask extends "default" ? MaskDefault : Mask, PinnedParams > extends readonly [infer UnpinnedParams extends readonly unknown[], unknown] ? _DeReadonly< ApplyArgs< Mask extends "default" ? MaskDefault : Mask, PinnedParams, UnpinnedParams > > : never, ResolveGenericSignature< F["GenericResolver"], Mask extends "default" ? MaskDefault : Mask, PinnedParams > extends readonly [readonly unknown[], infer R] ? R : never > { def: () => ApplyW>; } /** * Call a type level function with the given argument list. * * Type safety is **guaranteed**. * * @example * ```typescript * type R1 = Call; * // ^?: "42" * type R2 = Call; * // ^?: "foobar" * ``` */ export type Apply> = ApplyW; /** * The **unsafe** version of {@link Apply} (i.e. no type checking with `F` and `Args`). */ export type ApplyW = F & { readonly Args: (_: Args) => void } extends { readonly def: (...args: never[]) => infer R } ? R : never; /** * Apply a type level function with variadic arguments (up to 4 arguments). * * Type safety is **guaranteed**. * * @example * ```typescript * type R1 = Call; * // ^?: "42" * type R2 = Call; * // ^?: "foobar" * ``` */ export type Call< F extends Fn0 | Fn1 | Fn2 | Fn3 | Fn4, A extends ParamsLength extends 1 | 2 | 3 | 4 ? Params[0] : never = never, B extends ParamsLength extends 2 | 3 | 4 ? Params[1] : never = never, C extends ParamsLength extends 3 | 4 ? Params[2] : never = never, D extends ParamsLength extends 4 ? Params[3] : never = never, > = F & { readonly Args: (_: [A, B, C, D]) => void } extends ( { readonly def: (...args: never[]) => infer R } ) ? R : never; /** * Apply a type level function with variadic arguments (up to 4 arguments). * * Alias of {@link Call}. * * Type safety is **guaranteed**. * * @example * ```typescript * type R1 = $; * // ^?: "42" * type R2 = $; * // ^?: "foobar" * ``` */ export type $< F extends Fn0 | Fn1 | Fn2 | Fn3 | Fn4, A extends ParamsLength extends 1 | 2 | 3 | 4 ? Params[0] : never = never, B extends ParamsLength extends 2 | 3 | 4 ? Params[1] : never = never, C extends ParamsLength extends 3 | 4 ? Params[2] : never = never, D extends ParamsLength extends 4 ? Params[3] : never = never, > = Call; export type Call0 = Call0W; export type Call0W = F extends { readonly def: (...args: never[]) => infer R } ? R : never; export type Call1> = Call1W; export type Call1W = F & { readonly Args: (_: [A]) => void } extends { readonly def: (...args: never[]) => infer R } ? R : never; export type Call2, B extends Param1> = Call2W; export type Call2W = F & { readonly Args: (_: [A, B]) => void } extends ( { readonly def: (...args: never[]) => infer R } ) ? R : never; /** * Keep only the arguments that are not masked by `1` in `Mask`. * * `Params` and `Mask` should be the same length. * * @example * ```typescript * type R = MaskPinnedArgs<[string, number, boolean], "1_1">; * // ^?: [number] * ``` */ type MaskPinnedArgs = Params extends readonly [infer ParamsHead, ...infer ParamsTail] ? Mask extends `${infer Mask}${infer RestMask}` ? Mask extends "1" ? MaskPinnedArgs : [ParamsHead, ...MaskPinnedArgs] : Params : []; /** * Replace `1` in `Mask` with the corresponding value in `PinnedArgs` and `_` in `Mask` with the * the corresponding value in `AppliedArgs` (i.e. apply the arguments). * * The number of `1` and `_` should match the length of `PinnedArgs` and `AppliedArgs` respectively. * * @example * ```typescript * type R = ApplyArgs<"1__1", [true, "foo"], [12, "bar"]>; * // ^?: [true, 12, "bar", "foo"] * ``` */ type ApplyArgs = Mask extends `${infer Mask}${infer RestMask}` ? Mask extends "1" ? PinnedArgs extends readonly [infer PinnedArgsHead, ...infer PinnedArgsTail] ? [PinnedArgsHead, ...ApplyArgs] : never : AppliedArgs extends readonly [infer AppliedArgsHead, ...infer AppliedArgsTail] ? [AppliedArgsHead, ...ApplyArgs] : never : []; /** * Replace each `1` in `Mask` with the corresponding value in `PinnedArgs` and `_` with `never`. * * @example * ```typescript * type R = BuildPartialArgs<"1__1", [true, "foo"]>; * // ^?: [true, never, never, "foo"] * ``` */ type BuildPartialArgs = Mask extends `${infer Mask}${infer RestMask}` ? Mask extends "1" ? PinnedArgs extends readonly [infer AppliedArgsHead, ...infer AppliedArgsTail] ? [AppliedArgsHead, ...BuildPartialArgs] : never : [never, ...BuildPartialArgs] : []; interface PartialApplyNormal< F extends Fn, Mask extends string, PinnedArgs extends readonly unknown[], > extends Fn, Mask>, Return> { readonly def: () => ApplyW>>; } interface PartialApplyGeneric< F extends Fn & { readonly GenericResolver: Fn }, Mask extends string, PinnedArgs extends readonly unknown[], > extends Fn< ResolveGenericSignature extends ( [infer Args extends readonly unknown[], unknown] ) ? _DeReadonly : never, ResolveGenericSignature extends ( [readonly unknown[], infer Return] ) ? Return : never > { readonly GenericResolver: PartialApplyGenericResolver; readonly def: () => ApplyW>>; } /** * Partially apply a type level function with the given argument list. * * Type safety is **not guaranteed**. * * @example * ```typescript * type F1 = PartialApplyW; * // ^?: Fn<[string], string> * type R1 = $; * // ^?: "foobar" * type F2 = PartialApplyW; * // ^?: Fn<[string], string> * type R2 = $; * // ^?: "foobar" * ``` */ export type PartialApplyW< F extends Fn, PinnedArgs extends readonly unknown[], Mask extends string = "default", > = F extends { readonly GenericResolver: Fn } ? PartialApplyGeneric : Mask, PinnedArgs> : PartialApplyNormal : Mask, PinnedArgs>; /** * Partially apply a type level function with the given argument list. * * Type safety is **guaranteed**. * * @example * ```typescript * type F1 = PartialApply; * // ^?: Fn<[string], string> * type R1 = $; * // ^?: "foobar" * type F2 = PartialApply; * // ^?: Fn<[string], string> * type R2 = $; * // ^?: "foobar" * ``` */ export type PartialApply< F extends Fn, PinnedArgs extends Mask extends "default" ? LegalPinnedArgsDefault : LegalPinnedArgs, Mask extends string = "default", > = PartialApplyW; type MaskDefault = _MaskDefault< Params, PinnedArgs >; type _MaskDefault = Params extends readonly [unknown, ...infer ParamsTail] ? PinnedArgs extends readonly [unknown, ...infer PinnedArgsTail] ? `1${_MaskDefault}` : `_${_MaskDefault}` : ""; type LegalPinnedArgsDefault = _LegalPinnedArgsDefault>; type _LegalPinnedArgsDefault = Args extends readonly [...infer Init, unknown] ? Init | Args : readonly []; type LegalPinnedArgs = _LegalPinnedArgs, RestMask>; type _LegalPinnedArgs = RestParams extends readonly [infer Head, ...infer Tail] ? RestMask extends `${infer Mask}${infer RestMask}` ? Mask extends "1" ? [Head, ..._LegalPinnedArgs] : _LegalPinnedArgs : never : readonly []; type Tail = TS extends readonly [unknown, ...infer Tail] ? Tail : []; type _CurryReturn = Args["length"] extends 0 ? Return : Fn1>; /** * Curry a type level function. * * Type safety is **guaranteed**. * * @example * ```typescript * type F = Curry; * // ^?: Fn<[string], Fn<[string], string>> * type R = $<$, "bar">; * // ^?: "foobar" * ``` */ export type Curry = F extends { readonly GenericResolver: Fn } ? CurryGeneric : CurryNormal; interface CurryNormal extends Fn< ParamsLength extends 0 ? [] : [Param0], _CurryReturn>, Return> > { readonly def: () => ParamsLength extends 0 ? ApplyW : ParamsLength extends 1 ? ApplyW]> : Curry]>>; } interface CurryGeneric extends Fn< ParamsLength extends 0 ? [] : [Param0], _CurryReturn>, Return> & { readonly GenericResolver: PartialApplyGenericResolverBy1>; } > { readonly GenericResolver: CurryGenericResolver; readonly def: () => ParamsLength extends 0 ? ApplyW : ParamsLength extends 1 ? ApplyW]> : Curry]>>; } /** * Flip the order of the first two arguments of a type level function. * * Sig1: `(f: (x: T, y: U) => V) => (y: U, x: T) => V` * * Sig2: `(f: (x: T) => (y: U) => V) => (y: U) => (x: T) => V` */ export type Flip> = F extends Fn2 ? F extends { readonly GenericResolver: Fn } ? Flip2Generic : Flip2Normal : F extends { readonly GenericResolver: Fn } ? Return extends { readonly GenericResolver: Fn } ? F extends ( Fn1 & { readonly GenericResolver: Fn }> & { readonly GenericResolver: Fn; } ) ? Flip1GenericGeneric : never : F extends Fn1> & { readonly GenericResolver: Fn } ? Flip1GenericNormal : never : Return extends { readonly GenericResolver: Fn } ? F extends Fn1 & { readonly GenericResolver: Fn }> ? Flip1NormalGeneric : never : F extends Fn1 & { readonly GenericResolver: Fn }> ? Flip1NormalNormal : never; interface Flip2Normal extends Fn<[Param1, Param0], Return> { readonly def: () => ApplyW, Arg0]>; } interface Flip2Generic extends GenericFn<[Param1, Param0], Return> { readonly GenericResolver: _Flip2GenericResolver; readonly def: () => ApplyW, Arg0]>; } interface _Flip2GenericResolver extends GenericResolver<2> { on__: () => ApplyGenericResolver; on1_: () => ApplyGenericResolver, never]>; on_1: () => ApplyGenericResolver, never, never]>; on11: () => ApplyGenericResolver, Arg0, never]>; } interface Flip1NormalNormal> extends Fn<[Param0>], Fn1, Return>>> { readonly def: () => _Flip1NormalNormal>; } interface _Flip1NormalNormal, A> extends Fn<[Param0], Return>> { readonly def: () => ApplyW>, A>; } interface Flip1NormalGeneric> extends GenericFn<[Param0>], Fn1, Return>>> { readonly GenericResolver: _Flip1NormalGenericResolver; readonly def: () => _Flip1NormalGeneric>; } interface _Flip1NormalGenericResolver> extends GenericResolver<[Param0>], Fn1, Return>>> { on1: () => [[], ApplyGenericResolver["GenericResolver"], "1", [Arg0, never]>]; } interface _Flip1NormalGeneric, A> extends Fn<[Param0], GenericReturn1W, A>> { readonly def: () => ApplyW>, A>; } interface Flip1GenericNormal & { readonly GenericResolver: Fn }> extends Fn<[Param0>], Fn1, Return>>> { readonly def: () => _Flip1GenericNormal>; } interface _Flip1GenericNormal & { readonly GenericResolver: Fn }, A> extends GenericFn<[Param0], Return>> { readonly GenericResolver: _Flip1GenericNormalResolver; readonly def: () => ApplyW>, A>; } interface _Flip1GenericNormalResolver & { readonly GenericResolver: Fn }> extends GenericResolver<[Param0], Return>> { on1: () => [[], ApplyGenericResolver, never]>]; } interface Flip1GenericGeneric< F extends Fn1 & { readonly GenericResolver: Fn }, > extends GenericFn<[Param0>], Fn1, Return>>> { readonly GenericResolver: _Flip1GenericGenericResolverOuter; readonly def: () => _Flip1GenericGeneric>; } interface _Flip1GenericGenericResolverOuter< F extends Fn1 & { readonly GenericResolver: Fn }, > extends GenericResolver<[Param0>], Fn1, Return>>> { on1: () => [ [], FnW< ApplyGenericResolver, never>]>, GenericReturn1W, Arg0> >, ]; } interface _Flip1GenericGeneric< F extends Fn1 & { readonly GenericResolver: Fn }, A, > extends GenericFn<[Param0], GenericReturn1W, A>> { readonly GenericResolver: _Flip1GenericGenericResolverInner; readonly def: () => ApplyW>, A>; } interface _Flip1GenericGenericResolverInner< F extends Fn1 & { readonly GenericResolver: Fn }, > extends GenericResolver<[Param0], Return>> { on1: () => [[], ApplyGenericResolver, never]>]; } /** * A type level function that always returns the same value. * * @example * ```typescript * type Always42 = Always<42>; * type S = Sig; * // ^?: () => 42 * type R = $; * // ^?: 42 * ``` */ export interface Always extends Fn<[], T> { def: () => T; } interface ComposeNormal>, A extends Fn1> extends Fn1, GenericReturn1W>> { readonly def: () => Call1W>>; } interface _CombineGenericResolver1 extends GenericResolver<1> { on_: () => [ [ ApplyGenericResolver, never]> extends ( [readonly [infer P], unknown] ) ? P : never, ], ApplyGenericResolver, never]> extends ( [readonly [unknown], infer R] ) ? R : never, ]; on1: () => ApplyGenericResolver, never]> extends ( [readonly [], infer R] ) ? ApplyGenericResolver : never; } interface ComposeGeneric< B extends Fn1> & { readonly GenericResolver: Fn2 }, A extends Fn1 & { readonly GenericResolver: Fn2 }, > extends Fn1, GenericReturn1W>> { readonly GenericResolver: _CombineGenericResolver1; readonly def: () => Call1W>>; } /** * Compose two type level functions (from right to left). * * Type safety is **guaranteed**. * * @example * ```typescript * type F = Compose, Str.ToUpperCase>; * // ^?: Fn<[string], string> * type R = $; * // ^?: "fooBAR" * ``` */ export type Compose>, A extends Fn1> = A extends Fn1 & { readonly GenericResolver: Fn2 } ? B extends Fn1> & { readonly GenericResolver: Fn2 } ? ComposeGeneric : ComposeNormal : ComposeNormal; /** * The **unsafe** version of {@link Compose} (i.e. no type checking with `A` and `B`). */ export type ComposeW = A extends Fn1 & { readonly GenericResolver: Fn2 } ? B extends Fn1> & { readonly GenericResolver: Fn2 } ? ComposeGeneric : B extends Fn1> ? ComposeNormal : never : A extends Fn1 ? B extends Fn1> ? ComposeNormal : never : never; /** * Get return type of a possibly generic {@link Fn} from its generic resolver if exists. */ export type GenericReturn< F extends Fn, PinnedArgs extends Mask extends "default" ? LegalPinnedArgsDefault : LegalPinnedArgs, Mask extends string = "default", > = F extends { readonly GenericResolver: infer Resolver extends Fn } ? ResolveGenericSignature< Resolver, Mask extends "default" ? MaskDefault : Mask, PinnedArgs > extends readonly [[], infer R] ? R : never : Return; /** * The **unsafe** version of {@link GenericReturn} (i.e. no type checking with `F` and `Args`). */ export type GenericReturnW = F extends { readonly GenericResolver: infer Resolver extends Fn } ? PinnedArgs extends unknown[] ? ResolveGenericSignature< Resolver, Mask extends "default" ? F extends Fn ? MaskDefault : never : Mask, PinnedArgs > extends readonly [[], infer R] ? R : never : never : F extends Fn ? Return : never; /** * A shorthand for `GenericReturn`. * * @see {@link GenericReturn} */ export type GenericReturn1> = F extends { readonly GenericResolver: infer Resolver extends Fn2 } ? ResolveGenericSignature extends readonly [[], infer R] ? R : never : Return; /** * The **unsafe** version of {@link GenericReturn1} (i.e. no type checking with `F` and `A`). */ export type GenericReturn1W = F extends { readonly GenericResolver: infer Resolver extends Fn2 } ? ResolveGenericSignature extends readonly [[], infer R] ? R : never : F extends Fn1 ? Return : never; /** * Compose a list of type level functions (from left to right). * Supports up to 16 functions. * * Type safety is **guaranteed**. * * @example * ```typescript * type F = Flow, Str.ToLowerCase>; * // ^?: Fn<[string], string> * type R = $; * // ^?: "foobar" * ``` */ export type Flow< A extends Fn1, B extends Fn1> = never, C extends Fn1>> = never, D extends Fn1>>> = never, E extends Fn1>>>> = never, // prettier-ignore F extends Fn1>>>>> = never, // prettier-ignore G extends Fn1>>>>>> = never, // prettier-ignore H extends Fn1>>>>>>> = never, // prettier-ignore I extends Fn1>>>>>>>> = never, // prettier-ignore J extends Fn1>>>>>>>>> = never, // prettier-ignore K extends Fn1>>>>>>>>>> = never, // prettier-ignore L extends Fn1>>>>>>>>>>> = never, // prettier-ignore M extends Fn1>>>>>>>>>>>> = never, // prettier-ignore N extends Fn1>>>>>>>>>>>>> = never, // prettier-ignore O extends Fn1>>>>>>>>>>>>>> = never, // prettier-ignore P extends Fn1>>>>>>>>>>>>>>> = never, > = [B] extends [never] ? A : [C] extends [never] ? ComposeW : [D] extends [never] ? ComposeW> : [E] extends [never] ? ComposeW>> : [F] extends [never] ? ComposeW>>> : [G] extends [never] ? ComposeW>>>> : [H] extends [never] ? ComposeW>>>>> : [I] extends [never] ? ComposeW>>>>>> : [J] extends [never] ? // prettier-ignore ComposeW>>>>>>> : [K] extends [never] ? // prettier-ignore ComposeW>>>>>>>> : [L] extends [never] ? // prettier-ignore ComposeW>>>>>>>>> : [M] extends [never] ? // prettier-ignore ComposeW>>>>>>>>>> : [N] extends [never] ? // prettier-ignore ComposeW>>>>>>>>>>> : [O] extends [never] ? // prettier-ignore ComposeW>>>>>>>>>>>> : [P] extends [never] ? // prettier-ignore ComposeW>>>>>>>>>>>>> : // prettier-ignore ComposeW>>>>>>>>>>>>>>; export type Flows = FS extends readonly [infer Head extends Fn1] ? Head : FS extends readonly [infer Head extends Fn1, ...infer Tail extends readonly Fn1[]] ? // @ts-expect-error - TS cannot guarantee tail functions are compatible with head Compose, Head> : never; /** * Pipe value through variadic type level functions (from left to right). * Supports up to 16 functions. * * Type safety is **guaranteed**. * * @example * ```typescript * type R = Pipe<"bAr", Str.ToUpperCase, Str.Prepend<"foo">, Str.ToLowerCase>; * // ^?: "foobar" * ``` */ export type Pipe< T, A extends Fn1, B extends Fn1> = never, C extends Fn1>> = never, D extends Fn1>>> = never, // prettier-ignore E extends Fn1>>>> = never, // prettier-ignore F extends Fn1>>>>> = never, // prettier-ignore G extends Fn1>>>>>> = never, // prettier-ignore H extends Fn1>>>>>>> = never, // prettier-ignore I extends Fn1>>>>>>>> = never, // prettier-ignore J extends Fn1>>>>>>>>> = never, // prettier-ignore K extends Fn1>>>>>>>>>> = never, // prettier-ignore L extends Fn1>>>>>>>>>>> = never, // prettier-ignore M extends Fn1>>>>>>>>>>>> = never, // prettier-ignore N extends Fn1>>>>>>>>>>>>> = never, // prettier-ignore O extends Fn1>>>>>>>>>>>>>> = never, // prettier-ignore P extends Fn1>>>>>>>>>>>>>>> = never, > = [B] extends [never] ? Call1W : [C] extends [never] ? Call1W> : [D] extends [never] ? Call1W>> : [E] extends [never] ? Call1W>>> : [F] extends [never] ? Call1W>>>> : [G] extends [never] ? Call1W>>>>> : [H] extends [never] ? Call1W>>>>>> : [I] extends [never] ? Call1W>>>>>>> : [J] extends [never] ? // prettier-ignore Call1W>>>>>>>> : [K] extends [never] ? // prettier-ignore Call1W>>>>>>>>> : [L] extends [never] ? // prettier-ignore Call1W>>>>>>>>>> : [M] extends [never] ? // prettier-ignore Call1W>>>>>>>>>>> : [N] extends [never] ? // prettier-ignore Call1W>>>>>>>>>>>> : [O] extends [never] ? // prettier-ignore Call1W>>>>>>>>>>>>> : [P] extends [never] ? // prettier-ignore Call1W>>>>>>>>>>>>>> : // prettier-ignore Call1W>>>>>>>>>>>>>>>;