[TypeScript] Type Challenges #3196 - Flip Arguments

11 阅读1分钟

题目描述

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

题解

// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'

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


// ============= Your Code Here =============
type Reverse<T extends unknown[]> = 
  T extends [infer Head, ...infer Tail]
    ? [...Reverse<Tail>, Head]
    : []

type FlipArguments<
  T extends (...args: any) => any
> =
  (...args: Reverse<Parameters<T>>) => ReturnType<T>

辅助类型:Reverse<T>

type Reverse<T extends unknown[]> = 
  T extends [infer Head, ...infer Tail]
    ? [...Reverse<Tail>, Head]
    : []
  • 如果T是非空数组:

    • 使用infer Head推断T的第一个元素

    • 使用...infer Tail推断T的剩余部分

    • [...Reverse<Tail>, Head]

      • 递归调用Reverse<Tail>反转剩余部分

      • Head追加到数组末尾

  • 如果T是空数组:

    • 返回[]

主类型:FlipArguments<T>

type FlipArguments<
  T extends (...args: any) => any
> =
  (...args: Reverse<Parameters<T>>) => ReturnType<T>
  • 使用Parameters<T>提取函数T的参数列表

  • 使用Reverse<Parameters<T>>反转参数列表

  • 使用ReturnType<T>提取函数T的返回值类型

  • 返回一个新的函数类型,其参数列表为反转后的Reverse<Parameters<T>>,返回值类型为ReturnType<T>