#3196Medium

Flip Arguments

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.

Challenge Instructions: Flip Arguments

Medium

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) => void

Change the following code to make the test cases pass (no type check errors).

ChallengeSolution
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>,
]

Pro Challenge

Unlock 102+ medium, hard, and extreme challenges to master advanced TypeScript.

One-time payment. Lifetime access.

Detailed Explanation

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
    : never

How it works:

An 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
    : never

However, 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.

Share this challenge