// oxlint-disable explicit-module-boundary-types // oxlint-disable no-explicit-any import type { AnyFunction, AnyGeneratorFunction } from "./is.ts" import type { TupleAt, TupleHead, TupleLast, TuplePrev, TupleReverse, TupleTail } from "./tuple.ts" // ============================================================================ // Primitives // ============================================================================ /** * @description Type for a no-operation function. * * @example * ``` * // Expect: () => void * type Example1 = FunctionNoop * ``` */ export type FunctionNoop = () => void /** * @description Type for an identity function. * * @example * ``` * // Expect: (x: string) => string * type Example1 = FunctionIdentity * // Expect: (x: number) => number * type Example2 = FunctionIdentity * ``` */ export type FunctionIdentity = (x: T) => T /** * @description Type for a constant function. * * @example * ``` * // Expect: () => string * type Example1 = FunctionConstant * // Expect: () => number * type Example2 = FunctionConstant * ``` */ export type FunctionConstant = () => T /** * @description Interface for type guard functions that use type predicates. * * Type predicates allow functions to narrow types at compile time. * * @example * ``` * // Expect: valid predicate function * const isString: FunctionPredicate = (value: unknown): value is string => typeof value === 'string' * // Expect: valid predicate function * const isNumber: FunctionPredicate = (value: unknown): value is number => typeof value === 'number' * ``` * * @see {@link https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates} * @see {@link https://github.com/ts-essentials/ts-essentials#predicatetype} */ export interface FunctionPredicate { (target: Target, ..._: unknown[]): target is Target (target: unknown, ..._: unknown[]): target is Target } /** * @description Type for a mapper function. * * @example * ``` * // Expect: (x: string) => number * type Example1 = FunctionMapper * // Expect: (x: boolean) => string * type Example2 = FunctionMapper * ``` */ export type FunctionMapper = (x: T) => U /** * @description Type for a reducer function. * * @example * ``` * // Expect: (acc: number, x: string) => number * type Example1 = FunctionReducer * ``` */ export type FunctionReducer = (acc: Acc, x: T) => Acc /** * @description Type for a comparator function. * * @example * ``` * // Expect: (a: number, b: number) => number * type Example1 = FunctionComparator * // Expect: (a: string, b: string) => number * type Example2 = FunctionComparator * ``` */ export type FunctionComparator = (a: T, b: T) => number /** * @description Type for a callback function. * * @example * ``` * // Expect: (value: string) => void * type Example1 = FunctionCallback * // Expect: (value: number) => void * type Example2 = FunctionCallback * ``` */ export type FunctionCallback = (value: T) => void /** * @description Type for an event handler function. * * @example * ``` * type ClickEvent = { x: number; y: number } * // Expect: (event: ClickEvent) => void * type Example1 = FunctionEventHandler * ``` */ export type FunctionEventHandler = (event: E) => void /** * @description Type for an assertion function. * * @example * ``` * // Expect: (value: unknown) => asserts value is string * type Example1 = FunctionAssert * ``` */ export type FunctionAssert = (value: unknown) => asserts value is T /** * @description Type for a decorator function that wraps another function. * * @example * ``` * type Func = (a: number) => string * // Expect: (fn: Func) => Func * type Example1 = FunctionDecorator * ``` */ export type FunctionDecorator = (fn: F) => F /** * @description Type for a middleware function. * * @example * ``` * type Context = { req: Request; res: Response } * type Next = () => void * // Expect: (ctx: Context, next: Next) => void * type Example1 = FunctionMiddleware * ``` */ export type FunctionMiddleware = ( ctx: Context, next: Next, ) => ReturnType | Promise> /** * @description Type for an interceptor function. * * @example * ``` * type Value = string * // Expect: (value: string) => string | Promise * type Example1 = FunctionInterceptor * ``` */ export type FunctionInterceptor = (value: T) => T | Promise /** * @description Type for a memoized function (same signature but with cache). * * @example * ``` * type Func = (a: number, b: string) => boolean * // Expect: (a: number, b: string) => boolean * type Example1 = FunctionMemoized * ``` */ export type FunctionMemoized = F /** * @description Type for a throttled function. * * @example * ``` * type Func = (a: number) => void * // Expect: (a: number) => void * type Example1 = FunctionThrottled * ``` */ export type FunctionThrottled = F /** * @description Type for a debounced function. * * @example * ``` * type Func = (a: number) => void * // Expect: (a: number) => void * type Example1 = FunctionDebounced * ``` */ export type FunctionDebounced = F // ============================================================================ // Validation // ============================================================================ /** * @description Check if a function is synchronous (does not return Promise). * * @example * ``` * type Func1 = () => string * type Func2 = () => Promise * // Expect: true * type Example1 = FunctionIsSync * // Expect: false * type Example2 = FunctionIsSync * ``` */ export type FunctionIsSync = F extends (...args: any[]) => Promise ? false : F extends AnyFunction ? true : false /** * @description Check if a function is asynchronous (returns Promise). * * @example * ``` * type Func1 = () => Promise * type Func2 = () => string * // Expect: true * type Example1 = FunctionIsAsync * // Expect: false * type Example2 = FunctionIsAsync * ``` */ export type FunctionIsAsync = F extends (...args: any[]) => Promise ? true : false /** * @description Check if a function returns void. * * @example * ``` * type Func1 = () => void * type Func2 = () => string * // Expect: true * type Example1 = FunctionIsVoid * // Expect: false * type Example2 = FunctionIsVoid * ``` */ export type FunctionIsVoid = F extends (...args: any[]) => void ? true : false /** * @description Check if a function has variadic parameters (rest parameters). * * @example * ``` * type Func1 = (...args: string[]) => void * type Func2 = (a: string, b: number) => void * // Expect: true * type Example1 = FunctionIsVariadic * // Expect: false * type Example2 = FunctionIsVariadic * ``` */ export type FunctionIsVariadic = F extends (...args: infer P) => any ? P extends [...any[], ...infer Rest] ? Rest extends readonly any[] ? number extends Rest["length"] ? true : false : false : false : false /** * @description Check if a function has zero parameters. * * @example * ``` * type Func1 = () => string * type Func2 = (a: string) => string * // Expect: true * type Example1 = FunctionIsNullary * // Expect: false * type Example2 = FunctionIsNullary * ``` */ export type FunctionIsNullary = F extends () => any ? true : false /** * @description Check if a function has exactly one parameter. * * @example * ``` * type Func1 = (a: string) => string * type Func2 = (a: string, b: number) => string * // Expect: true * type Example1 = FunctionIsUnary * // Expect: false * type Example2 = FunctionIsUnary * ``` */ export type FunctionIsUnary = F extends (arg: any) => any ? true : false /** * @description Check if a function has exactly two parameters. * * @example * ``` * type Func1 = (a: string, b: number) => string * type Func2 = (a: string) => string * // Expect: true * type Example1 = FunctionIsBinary * // Expect: false * type Example2 = FunctionIsBinary * ``` */ export type FunctionIsBinary = F extends (arg1: any, arg2: any) => any ? true : false /** * @description Check if a function has exactly three parameters. * * @example * ``` * type Func1 = (a: string, b: number, c: boolean) => string * type Func2 = (a: string, b: number) => string * // Expect: true * type Example1 = FunctionIsTernary * // Expect: false * type Example2 = FunctionIsTernary * ``` */ export type FunctionIsTernary = F extends (arg1: any, arg2: any, arg3: any) => any ? true : false /** * @description Check if a function is a constructor function. * * @example * ``` * class MyClass {} * type Func = () => void * // Expect: true * type Example1 = FunctionIsConstructor * // Expect: false * type Example2 = FunctionIsConstructor * ``` */ export type FunctionIsConstructor = F extends new (...args: any[]) => any ? true : false /** * @description Check if a function is a generator function. * * @example * ``` * function* genFunc() { yield 1; yield 2; } * type Func = () => void * // Expect: true * type Example1 = FunctionIsGenerator * // Expect: false * type Example2 = FunctionIsGenerator * ``` */ export type FunctionIsGenerator = F extends (...args: any[]) => Generator ? true : false /** * @description Check if a function is an async generator function. * * @example * ``` * async function* asyncGenFunc() { yield 1; yield 2; } * type Func = () => void * // Expect: true * type Example1 = FunctionIsAsyncGenerator * // Expect: false * type Example2 = FunctionIsAsyncGenerator * ``` */ export type FunctionIsAsyncGenerator = F extends ( ...args: any[] ) => AsyncGenerator ? true : false // ============================================================================ // Comparison // ============================================================================ /** * @description Check if two functions have equal parameter types. * * @example * ``` * type F1 = (a: number, b: string) => void * type F2 = (a: number, b: string) => boolean * type F3 = (a: number) => void * // Expect: true * type Example1 = FunctionParametersEqual * // Expect: false * type Example2 = FunctionParametersEqual * ``` */ export type FunctionParametersEqual = Parameters extends Parameters ? Parameters extends Parameters ? true : false : false /** * @description Check if two functions have equal return types. * * @example * ``` * type F1 = (a: number) => string * type F2 = (b: boolean) => string * type F3 = (a: number) => number * // Expect: true * type Example1 = FunctionReturnEqual * // Expect: false * type Example2 = FunctionReturnEqual * ``` */ export type FunctionReturnEqual = ReturnType extends ReturnType ? ReturnType extends ReturnType ? true : false : false /** * @description Check if two functions have equal signatures. * * @example * ``` * type F1 = (a: number, b: string) => boolean * type F2 = (a: number, b: string) => boolean * type F3 = (a: number) => boolean * // Expect: true * type Example1 = FunctionSignatureEqual * // Expect: false * type Example2 = FunctionSignatureEqual * ``` */ export type FunctionSignatureEqual = FunctionParametersEqual extends true ? FunctionReturnEqual : false /** * @description Check if function F1 is compatible with (assignable to) F2. * * @example * ``` * type F1 = (a: number) => string * type F2 = (a: number) => string | number * // Expect: true * type Example1 = FunctionCompatible * ``` */ export type FunctionCompatible = F1 extends F2 ? true : false // ============================================================================ // Query // ============================================================================ /** * @description Get the parameter length of a function type. * * @example * ``` * type Func1 = (a: number, b: string) => string * type Func2 = (...args: string[]) => string * // Expect: 2 * type Example1 = FunctionLength * // Expect: number * type Example2 = FunctionLength * // Expect: never * type Example3 = FunctionLength * ``` */ export type FunctionLength = F extends (...args: infer Parameters) => any ? Parameters["length"] : never /** * @description Get the arity (parameter count) of a function. * * @example * ``` * type Func1 = (a: number, b: string) => string * type Func2 = () => void * // Expect: 2 * type Example1 = FunctionArity * // Expect: 0 * type Example2 = FunctionArity * ``` */ export type FunctionArity = FunctionLength /** * @description Extract the first parameter type of a function. * * @example * ``` * type Func = (a: number, b: string) => void * // Expect: number * type Example1 = FunctionFirstParameter * type NoParam = () => void * // Expect: never * type Example2 = FunctionFirstParameter * ``` */ export type FunctionFirstParameter = TupleHead> /** * @description Extract the last parameter type of a function. * * @example * ``` * type Func = (a: number, b: string) => void * // Expect: string * type Example1 = FunctionLastParameter * type Single = (a: number) => void * // Expect: number * type Example2 = FunctionLastParameter * ``` */ export type FunctionLastParameter = TupleLast> /** * @description Extract the parameter type at index N. * * @example * ``` * type Func = (a: number, b: string, c: boolean) => void * // Expect: number * type Example1 = FunctionParameterAt * // Expect: string * type Example2 = FunctionParameterAt * // Expect: boolean * type Example3 = FunctionParameterAt * ``` */ export type FunctionParameterAt = TupleAt, N> /** * @description Extract rest parameters from a function (all parameters except the first). * * @example * ``` * type Func = (a: number, b: string, c: boolean) => void * // Expect: [string, boolean] * type Example1 = FunctionRestParameters * type Single = (a: number) => void * // Expect: [] * type Example2 = FunctionRestParameters * ``` */ export type FunctionRestParameters = TupleTail> /** * @description Extract the predicated type from a type guard function. * * @example * ``` * const isString = (value: unknown): value is string => typeof value === 'string' * const isNumber = (value: unknown): value is number => typeof value === 'number' * // Expect: string * type Example1 = PredicateTypeOf * // Expect: number * type Example2 = PredicateTypeOf * ``` * * @see {@link https://github.com/ts-essentials/ts-essentials#predicatetype} */ export type FunctionPredicateType = F extends (( target: unknown, ...rest: any[] ) => target is infer P) ? P : never /** * @description Extract the yield type from a generator function. * * @example * ``` * type GenFunc = () => Generator * // Expect: string * type Example1 = FunctionGeneratorYield * ``` */ export type FunctionGeneratorYield = ReturnType extends Generator ? Y : never /** * @description Extract the return type from a generator function. * * @example * ``` * type GenFunc = () => Generator * // Expect: number * type Example1 = FunctionGeneratorReturn * ``` */ export type FunctionGeneratorReturn = ReturnType extends Generator ? R : never /** * @description Extract the next parameter type from a generator function. * * @example * ``` * type GenFunc = () => Generator * // Expect: boolean * type Example1 = FunctionGeneratorNext * ``` */ export type FunctionGeneratorNext = ReturnType extends Generator ? N : never // ============================================================================ // Manipulation (this) // ============================================================================ /** * @description Extract the this type from a function. * * @example * ``` * type Func = (this: { x: number }, a: string) => void * // Expect: { x: number } * type Example1 = FunctionThisType * type NoThis = (a: string) => void * // Expect: unknown * type Example2 = FunctionThisType * ``` */ export type FunctionThisType = F extends (this: infer This, ...args: any[]) => any ? This : unknown /** * @description Bind this type to a function. * * @example * ``` * type Func = (a: string) => void * // Expect: (this: { x: number }, a: string) => void * type Example1 = FunctionBindThis * ``` */ export type FunctionBindThis = F extends (...args: infer P) => infer R ? (this: This, ...args: P) => R : never /** * @description Remove this parameter from a function. * * @example * ``` * type Func = (this: { x: number }, a: string, b: number) => void * // Expect: (a: string, b: number) => void * type Example1 = FunctionOmitThis * type NoThis = (a: string) => void * // Expect: (a: string) => void * type Example2 = FunctionOmitThis * ``` */ export type FunctionOmitThis = F extends (this: any, ...args: infer P) => infer R ? (...args: P) => R : F /** * @description Convert function to arrow function type (removes this). * * @example * ``` * type Func = (this: { x: number }, a: string) => void * // Expect: (a: string) => void * type Example1 = FunctionToArrow * ``` */ export type FunctionToArrow = FunctionOmitThis /** * @description Add this parameter to a function that doesn't have one. * * @example * ``` * type Func = (a: string) => void * // Expect: (this: { x: number }, a: string) => void * type Example1 = FunctionWithThis * ``` */ export type FunctionWithThis = FunctionBindThis // ============================================================================ // Manipulation (whole) // ============================================================================ /** * @description Convert a function type to return a Promise of its original return type. * * @example * ``` * type Func = (a: number, b: string) => string * // Expect: (a: number, b: string) => Promise * type Example1 = FunctionPromisify * type VoidFunc = () => void * // Expect: () => Promise * type Example2 = FunctionPromisify * ``` */ export type FunctionPromisify = ( ...args: Parameters ) => Promise> /** * @description Alias for FunctionPromisify. * * @example * ``` * type Func = (a: number) => string * // Expect: (a: number) => Promise * type Example1 = FunctionAsyncify * ``` */ export type FunctionAsyncify = FunctionPromisify /** * @description Convert function parameters to Promises and return Promise of result. * * @example * ``` * type Func = (a: number, b: string) => boolean * // Expect: (a: Promise, b: Promise) => Promise * type Example1 = FunctionPromisifyAll * ``` */ export type FunctionPromisifyAll = Parameters extends [infer First, ...infer Rest] ? Rest extends [] ? (a: Promise) => Promise> : ( a: Promise, ...args: { [K in keyof Rest]: Promise } ) => Promise> : F /** * @description Unwrap Promise return type to make function synchronous. * * @example * ``` * type AsyncFunc = () => Promise * // Expect: () => string * type Example1 = FunctionSyncify * type SyncFunc = () => string * // Expect: () => string * type Example2 = FunctionSyncify * ``` */ export type FunctionSyncify = ReturnType extends Promise ? (...args: Parameters) => T : F /** * @description Convert function return type to void. * * @example * ``` * type Func = (a: number) => string * // Expect: (a: number) => void * type Example1 = FunctionVoidify * ``` */ export type FunctionVoidify = (...args: Parameters) => void /** * @description Convert function return type to null. * * @example * ``` * type Func = (a: number) => string * // Expect: (a: number) => null * type Example1 = FunctionNullify * ``` */ export type FunctionNullify = (...args: Parameters) => null /** * @description Make all function parameters optional. * * @example * ``` * type Func = (a: number, b: string) => void * // Expect: (a?: number, b?: string) => void * type Example1 = FunctionOptionalify * ``` */ export type FunctionOptionalify = ( ...args: Partial> ) => ReturnType /** * @description Make all function parameters required. * * @example * ``` * type Func = (a?: number, b?: string) => void * // Expect: (a: number, b: string) => void * type Example1 = FunctionRequiredify * ``` */ export type FunctionRequiredify = ( ...args: Required> ) => ReturnType /** * @description Make all function parameters readonly. * * @example * ``` * type Func = (a: number[], b: { x: number }) => void * // Expect: (a: readonly number[], b: Readonly<{ x: number }>) => void * type Example1 = FunctionReadonly * ``` */ export type FunctionReadonly = ( ...args: Readonly> ) => ReturnType // ============================================================================ // Manipulation (parameters) // ============================================================================ /** * @description Check if a function has optional parameters. * * @example * ``` * type Func1 = (a: number, b?: string) => void * type Func2 = (a: number, b: string) => void * // Expect: true * type Example1 = FunctionHasOptionalParameters * // Expect: false * type Example2 = FunctionHasOptionalParameters * ``` */ export type FunctionHasOptionalParameters = Parameters extends Partial> ? Partial> extends Parameters ? false : true : false /** * @description Reverse the order of function parameters. * * @example * ``` * type Func = (a: string, b: number, c: boolean) => void * // Expect: (c: boolean, b: number, a: string) => void * type Example1 = FunctionReverseParameters * ``` */ export type FunctionReverseParameters = ( ...args: TupleReverse> ) => ReturnType type InternalInsertParameter< Params extends readonly any[], N extends number, T, Count extends readonly any[] = [], Acc extends readonly any[] = [], > = Count["length"] extends N ? [...Acc, T, ...Params] : Params extends [infer First, ...infer Rest] ? InternalInsertParameter : [...Acc, T] /** * @description Insert a parameter at index N in the function parameter list. * * @example * ``` * type Func = (a: string, c: boolean) => void * // Expect: (a: string, b: number, c: boolean) => void * type Example1 = FunctionInsertParameter * ``` */ export type FunctionInsertParameter = ( ...args: InternalInsertParameter, N, T> ) => ReturnType /** * @description Prepend a parameter to the function parameter list. * * @example * ``` * type Func = (b: string) => void * // Expect: (a: number, b: string) => void * type Example1 = FunctionPrependParameter * ``` */ export type FunctionPrependParameter = ( arg: T, ...args: Parameters ) => ReturnType /** * @description Append a parameter to the function parameter list. * * @example * ``` * type Func = (a: string) => void * // Expect: (a: string, b: number) => void * type Example1 = FunctionAppendParameter * ``` */ export type FunctionAppendParameter = ( ...args: [...Parameters, T] ) => ReturnType type InternalRemoveParameter< Params extends readonly any[], N extends number, Count extends readonly any[] = [], Acc extends readonly any[] = [], > = Params extends [infer First, ...infer Rest] ? Count["length"] extends N ? [...Acc, ...Rest] : InternalRemoveParameter : Acc /** * @description Remove the parameter at index N from the function parameter list. * * @example * ``` * type Func = (a: string, b: number, c: boolean) => void * // Expect: (a: string, c: boolean) => void * type Example1 = FunctionRemoveParameter * ``` */ export type FunctionRemoveParameter = ( ...args: InternalRemoveParameter, N> ) => ReturnType /** * @description Remove the first parameter from the function parameter list. * * @example * ``` * type Func = (a: string, b: number) => void * // Expect: (b: number) => void * type Example1 = FunctionRemoveFirstParameter * ``` */ export type FunctionRemoveFirstParameter = ( ...args: TupleTail> ) => ReturnType /** * @description Remove the last parameter from the function parameter list. * * @example * ``` * type Func = (a: string, b: number) => void * // Expect: (a: string) => void * type Example1 = FunctionRemoveLastParameter * ``` */ export type FunctionRemoveLastParameter = Parameters extends [...infer Init, any] ? (...args: Init) => ReturnType : () => ReturnType type InternalReplaceParameter< Params extends readonly any[], N extends number, T, Count extends readonly any[] = [], Acc extends readonly any[] = [], > = Params extends [infer First, ...infer Rest] ? Count["length"] extends N ? [...Acc, T, ...Rest] : InternalReplaceParameter : Acc /** * @description Replace the parameter at index N with a new type. * * @example * ``` * type Func = (a: string, b: number, c: boolean) => void * // Expect: (a: string, b: Date, c: boolean) => void * type Example1 = FunctionReplaceParameter * ``` */ export type FunctionReplaceParameter = ( ...args: InternalReplaceParameter, N, T> ) => ReturnType /** * @description Narrow parameter type to a more specific type. * * @example * ``` * type Func = (a: any) => void * // Expect: (a: number) => void * type Example1 = FunctionNarrowParameter * ``` */ export type FunctionNarrowParameter< F extends AnyFunction, Index extends number, Narrow, > = FunctionReplaceParameter /** * @description Widen parameter type to a more general type. * * @example * ``` * type Func = (a: number) => void * // Expect: (a: any) => void * type Example1 = FunctionWidenParameter * ``` */ export type FunctionWidenParameter< F extends AnyFunction, Index extends number, Widen, > = FunctionReplaceParameter type InternalSliceParameters< Params extends readonly any[], Start extends number, End extends number | undefined, Count extends readonly any[] = [], Acc extends readonly any[] = [], > = Params extends [infer First, ...infer Rest] ? Count["length"] extends End ? Acc : Start extends Count["length"] ? InternalSliceParameters : Count["length"] extends Start ? InternalSliceParameters : InternalSliceParameters : Acc /** * @description Slice parameters from Start to End (like Array.slice). * * @example * ``` * type Func = (a: number, b: string, c: boolean, d: symbol) => void * // Expect: (b: string, c: boolean) => void * type Example1 = FunctionSliceParameters * // Expect: (b: string, c: boolean, d: symbol) => void * type Example2 = FunctionSliceParameters * // Expect: (a: number, b: string) => void * type Example3 = FunctionSliceParameters * ``` */ export type FunctionSliceParameters< F extends AnyFunction, Start extends number, End extends number | undefined = undefined, > = (...args: InternalSliceParameters, Start, End>) => ReturnType /** * @description Pick specific parameters by index. * * @example * ``` * type Func = (a: number, b: string, c: boolean) => void * // Expect: (a: number, c: boolean) => void * type Example1 = FunctionPickParameters * ``` */ export type FunctionPickParameters = Parameters extends [...infer P] ? ( ...args: Array<{ [K in Indices]: K extends keyof P ? P[K] : never }[Indices]> ) => ReturnType : never /** * @description Omit specific parameters by index. * * @example * ``` * type Func = (a: number, b: string, c: boolean) => void * // Expect: (b: string) => void * type Example1 = FunctionOmitParameters * ``` */ export type FunctionOmitParameters = Parameters extends [...infer P] ? ( ...args: Array<{ [K in keyof P]: K extends `${Indices}` ? never : P[K] }[number]> ) => ReturnType : never /** * @description Flatten nested tuple parameters into a single parameter list. * * @example * ``` * type Func = (a: [number, string], b: [boolean]) => void * // Expect: (a: number, b: string, c: boolean) => void * type Example1 = FunctionFlattenParameters * ``` */ export type FunctionFlattenParameters = Parameters extends [infer A, ...infer Rest] ? A extends readonly any[] ? (...args: [...A, ...Rest]) => ReturnType : F : F /** * @description Group parameters into a tuple. * * @example * ``` * type Func = (a: number, b: string, c: boolean) => void * // Expect: (args: [number, string, boolean]) => void * type Example1 = FunctionGroupParameters * ``` */ export type FunctionGroupParameters = (args: Parameters) => ReturnType /** * @description Spread grouped parameters back to individual parameters. * * @example * ``` * type Func = (args: [number, string, boolean]) => void * // Expect: (a: number, b: string, c: boolean) => void * type Example1 = FunctionSpreadParameters * ``` */ export type FunctionSpreadParameters = Parameters extends [infer A] ? A extends readonly any[] ? (...args: A) => ReturnType : F : F /** * @description Distribute function over union parameters. * * @example * ``` * type Func = (a: number | string) => void * // Expect: ((a: number) => void) | ((a: string) => void) * type Example1 = FunctionDistributeParameters * ``` */ export type FunctionDistributeParameters = Parameters extends [infer First, ...infer Rest] ? First extends any ? (arg: First, ...rest: Rest) => ReturnType : never : F // ============================================================================ // Manipulation (return) // ============================================================================ /** * @description Map the return type of a function through a type transformation. * * @example * ``` * type Func = () => string * // Expect: () => string[] * type Example1 = FunctionMapReturn> * ``` */ export type FunctionMapReturn = (...args: Parameters) => R /** * @description Flatten nested Promise return types. * * @example * ``` * type Func = () => Promise> * // Expect: () => Promise * type Example1 = FunctionFlatReturn * ``` */ export type FunctionFlatReturn = ReturnType extends Promise ? Inner extends Promise ? (...args: Parameters) => Inner : F : F /** * @description Unwrap the return type (Promise or Array). * * @example * ``` * type AsyncFunc = () => Promise * type ArrayFunc = () => string[] * // Expect: () => string * type Example1 = FunctionUnwrapReturn * // Expect: () => string * type Example2 = FunctionUnwrapReturn * ``` */ export type FunctionUnwrapReturn = ReturnType extends Promise ? (...args: Parameters) => T : ReturnType extends Array ? (...args: Parameters) => U : F /** * @description Wrap the return type with a wrapper type. * * @example * ``` * type Func = () => string * // Expect: () => Promise * type Example1 = FunctionWrapReturn> * // Expect: () => Array * type Example2 = FunctionWrapReturn> * ``` */ export type FunctionWrapReturn = (...args: Parameters) => Wrapper /** * @description Convert return type to an array. * * @example * ``` * type Func = () => string * // Expect: () => string[] * type Example1 = FunctionReturnArray * type VoidFunc = () => void * // Expect: () => void[] * type Example2 = FunctionReturnArray * ``` */ export type FunctionReturnArray = ( ...args: Parameters ) => Array> /** * @description Convert return type to a tuple with one element. * * @example * ``` * type Func = () => string * // Expect: () => [string] * type Example1 = FunctionReturnTuple * ``` */ export type FunctionReturnTuple = (...args: Parameters) => [ReturnType] /** * @description Make return type nullable (add null | undefined). * * @example * ``` * type Func = () => string * // Expect: () => string | null | undefined * type Example1 = FunctionReturnNullable * ``` */ export type FunctionReturnNullable = ( ...args: Parameters ) => ReturnType | null | undefined /** * @description Remove null and undefined from return type. * * @example * ``` * type Func = () => string | null | undefined * // Expect: () => string * type Example1 = FunctionReturnNonNullable * type NoNull = () => string * // Expect: () => string * type Example2 = FunctionReturnNonNullable * ``` */ export type FunctionReturnNonNullable = ( ...args: Parameters ) => NonNullable> /** * @description Extract specific type from union return type. * * @example * ``` * type Func = () => string | number | boolean * // Expect: () => string * type Example1 = FunctionReturnExtract * // Expect: () => string | number * type Example2 = FunctionReturnExtract * ``` */ export type FunctionReturnExtract = ( ...args: Parameters ) => Extract, U> /** * @description Exclude specific type from union return type. * * @example * ``` * type Func = () => string | number | boolean * // Expect: () => number | boolean * type Example1 = FunctionReturnExclude * // Expect: () => boolean * type Example2 = FunctionReturnExclude * ``` */ export type FunctionReturnExclude = ( ...args: Parameters ) => Exclude, U> // ============================================================================ // Manipulation (functional) // ============================================================================ /** * @description Compose two functions (f1(f2(x))). * * @example * ``` * type F1 = (x: number) => string * type F2 = (x: boolean) => number * // Expect: (x: boolean) => string * type Example1 = FunctionCompose * ``` */ export type FunctionCompose = ReturnType extends Parameters[0] ? (...args: Parameters) => ReturnType : never /** * @description Pipe two functions (f2(f1(x))). * * @example * ``` * type F1 = (x: boolean) => number * type F2 = (x: number) => string * // Expect: (x: boolean) => string * type Example1 = FunctionPipe * ``` */ export type FunctionPipe = FunctionCompose interface FunctionComposeError { __compose_error__: true function: Fn expected: Expected got: Got } type FunctionComposeChain< Fns extends AnyFunction[], CurrentReturn, InitialArgs extends any[], > = Fns extends [] ? (...args: InitialArgs) => CurrentReturn : TupleLast extends (arg: infer A) => infer R ? [CurrentReturn] extends [A] ? FunctionComposeChain, R, InitialArgs> : FunctionComposeError, A, CurrentReturn> : never /** * @description Compose multiple functions from right to left. * * @example * ``` * type F1 = (x: string) => number * type F2 = (x: boolean) => string * type F3 = (x: symbol) => boolean * // Expect: (x: symbol) => number * type Example1 = FunctionComposeAll<[F1, F2, F3]> * ``` */ export type FunctionComposeAll = Fns extends [AnyFunction] ? Fns[0] : TupleLast extends (...args: infer Args) => infer R ? FunctionComposeChain, R, Args> : never /** * @description Pipe multiple functions from left to right. * * @example * ``` * type F1 = (x: symbol) => boolean * type F2 = (x: boolean) => string * type F3 = (x: string) => number * // Expect: (x: symbol) => number * type Example1 = FunctionPipeAll<[F1, F2, F3]> * ``` */ export type FunctionPipeAll = FunctionComposeAll< TupleReverse > /** * @description Create a union of function types. * * @example * ``` * type F1 = (a: number) => string * type F2 = (b: boolean) => number * // Expect: F1 | F2 * type Example1 = FunctionUnion * ``` */ export type FunctionUnion = F1 | F2 /** * @description Create an intersection of function types (overload). * * @example * ``` * type F1 = (a: number) => string * type F2 = (b: boolean) => number * // Expect: F1 & F2 (creates overload) * type Example1 = FunctionIntersection * ``` */ export type FunctionIntersection = F1 & F2 /** * @description Merge two function signatures (parameter union, return intersection). * * @example * ``` * type F1 = (a: number) => string * type F2 = (a: number) => number * // Expect: (a: number) => string & number (never) * type Example1 = FunctionMerge * ``` */ export type FunctionMerge = ( ...args: Parameters | Parameters ) => ReturnType & ReturnType type InternalCurry

= P extends [infer First, ...infer Rest] ? (arg: First) => Rest extends [] ? R : InternalCurry : R /** * @description Curry a function type. * * @example * ``` * type Func = (a: number, b: string, c: boolean) => void * // Expect: (a: number) => (b: string) => (c: boolean) => void * type Example1 = FunctionCurry * ``` */ export type FunctionCurry = InternalCurry, ReturnType> type InternalUncurry = F extends (arg: infer A) => infer R ? InternalUncurry : (...args: Acc) => F /** * @description Uncurry a curried function type. * * @example * ``` * type Curried = (a: number) => (b: string) => (c: boolean) => void * // Expect: (a: number, b: string, c: boolean) => void * type Example1 = FunctionUncurry * type Single = (a: number) => string * // Expect: (a: number) => string * type Example2 = FunctionUncurry * ``` */ export type FunctionUncurry = InternalUncurry type InternalPartialApply< P extends readonly any[], Applied extends readonly any[], > = Applied extends [] ? P : P extends [any, ...infer Rest] ? Applied extends [any, ...infer RestApplied] ? InternalPartialApply : P : P /** * @description Partially apply arguments to a function. * * @example * ``` * type Func = (a: number, b: string, c: boolean) => void * // Expect: (c: boolean) => void * type Example1 = FunctionPartialApply * ``` */ export type FunctionPartialApply = ( ...args: InternalPartialApply, Args> ) => ReturnType /** * @description Bind first N arguments of a function. * * @example * ``` * type Func = (a: number, b: string, c: boolean) => void * // Expect: (c: boolean) => void * type Example1 = FunctionBind * // Expect: (b: string, c: boolean) => void * type Example2 = FunctionBind * ``` */ export type FunctionBind< F extends AnyFunction, BoundArgs extends readonly any[], > = FunctionPartialApply // ============================================================================ // Conversion // ============================================================================ /** * @description Convert a regular function to a constructor function. * * @example * ``` * type Func = (a: number, b: string) => MyClass * // Expect: new (a: number, b: string) => MyClass * type Example1 = FunctionToClassConstructor * ``` */ export type FunctionToClassConstructor = new ( ...args: Parameters ) => Instance /** * @description Convert a function to an object method signature. * * @example * ``` * type Func = (a: number, b: string) => boolean * // Expect: { method(a: number, b: string): boolean } * type Example1 = FunctionToObject * ``` */ export type FunctionToObject = { [K in Key]: F }