Skip to content

Instantly share code, notes, and snippets.

@piotrwitek
Forked from gtkatakura/curry-variadic.ts
Created November 22, 2018 23:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save piotrwitek/f601ccfc69442de89367b36fd0852604 to your computer and use it in GitHub Desktop.
Save piotrwitek/f601ccfc69442de89367b36fd0852604 to your computer and use it in GitHub Desktop.
type Init<T extends any[], TTail extends any[] = TailArray<T>> = CastArray<{
[K in keyof TTail]: T[keyof T & K];
}>
type PotentialArgs<T extends any[], TResult extends any[] = T> = {
"continue": PotentialArgs<Init<T>, TResult | Init<T>>;
"end": TResult;
}[T extends [] ? "end" : "continue"]
type Args<T extends Function> =
T extends (...args: infer TArgs) => any ? TArgs
: never
type TailArgs<F extends Function> =
F extends (head: any, ...tail: infer TTail) => any ? TTail :
never
type TailArray<A extends any[]> = TailArgs<(...args: A) => any>
type CastArray<T> = T extends any[] ? T : []
type DropFromArraySize<TSource extends any[], TSize extends any[]> = CastArray<{
"continue": DropFromArraySize<TailArray<TSource>, TailArray<TSize>>,
"end": TSource,
}[TSize extends [] ? "end" : "continue"]>
type PartialArgs<T extends Function> =
T extends (...args: infer TArgs) => any ? Partial<TArgs>
: never
type Curried<T extends (...args: any) => any> =
<
TInitArgs extends PotentialArgs<Args<T>>,
TTailArgs extends DropFromArraySize<Args<T>, TInitArgs>
>(...args: TInitArgs) =>
TTailArgs extends []
? ReturnType<T>
: Curried<(...args: TTailArgs) => ReturnType<T>>
type Curry = <TFunc extends (...args: any) => any>(func: TFunc) => Curried<TFunc>
declare const curry: Curry
const curried = curry((a: 1 | undefined, b: number | number[], c: string) => 1)
// works :D
const a = curried(1)([2])('x')
const b = curried(1)(2, 'x')
const c = curried(1, 2)('x')
const d = curried(1, 2, 'x')
const e = curried(undefined)(2)('2')
curried(undefined)(2)(undefined) // notify error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment