Implement the type version of lodash's ```_.flip```. Master advanced TypeScript type manipulation in this medium-level challenge on TypeScriptPro.
In this medium-level challenge, you'll implement FlipArguments<T> which takes a function type and returns a new function type with the same return type but with its parameters reversed.
Implement the type version of lodash's _.flip.
Type FlipArguments<T> requires function type T and returns a new function type which has the same return type of T but reversed parameters.
For example:
type Flipped = FlipArguments<(arg0: string, arg1: number, arg2: boolean) => void>
// (arg0: boolean, arg1: number, arg2: string) => voidChange the following code to make the test cases pass (no type check errors).
type cases = [
Expect<Equal<FlipArguments<() => boolean>, () => boolean>>,
Expect<
Equal<FlipArguments<(foo: string) => number>, (foo: string) => number>
>,
Expect<
Equal<
FlipArguments<(arg0: string, arg1: number, arg2: boolean) => void>,
(arg0: boolean, arg1: number, arg2: string) => void
>
>,
]
type errors = [
// @ts-expect-error
FlipArguments<'string'>,
// @ts-expect-error
FlipArguments<{ key: 'value' }>,
// @ts-expect-error
FlipArguments<['apple', 'banana', 100, { a: 1 }]>,
// @ts-expect-error
FlipArguments<null | undefined>,
]
Unlock 102+ medium, hard, and extreme challenges to master advanced TypeScript.
One-time payment. Lifetime access.
We need a helper to reverse a tuple, then apply it to the function's parameter list.
type Reverse<T extends any[]> = T extends [infer First, ...infer Rest]
? [...Reverse<Rest>, First]
: []
type FlipArguments<T extends (...args: any[]) => any> =
T extends (...args: infer Args) => infer R
? (...args: Reverse<Args>) => R
: neverHow it works:
Reverse<T> recursively reverses a tuple by taking the first element, reversing the rest, and appending the first element at the endT extends (...args: infer Args) => infer R extracts the parameter tuple Args and return type R from the function typeReverse<Args> as the parameters and R as the return typeT extends (...args: any[]) => any ensures that only function types are accepted, causing non-function inputs to produce a type errorAn alternative approach uses a single type without a separate Reverse helper:
type FlipArguments<T extends (...args: any[]) => any> =
T extends (...args: infer Args) => infer R
? (...args: Args extends [...infer Rest, infer Last]
? [Last, ...FlipArguments<(...a: Rest) => R> extends (...a: infer P) => any ? P : never]
: []) => R
: neverHowever, the two-type approach with a separate Reverse is cleaner and easier to understand.
This challenge helps you understand function type manipulation with parameter tuple reversal and how to apply this concept in real-world scenarios.
This challenge is originally from here.