[TypeScript] Type Challenges #191 - Append Argument

103 阅读1分钟

题目描述

实现一个泛型AppendArgument<Fn, A>,对于给定的函数类型Fn,以及一个任意类型A,返回一个新的函数GG拥有Fn的所有参数并在末尾追加类型为A的参数。

type Fn = (a: number, b: string) => number

type Result = AppendArgument<Fn, boolean> 
// 期望是 (a: number, b: string, x: boolean) => number

题解

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

type Case1 = AppendArgument<(a: number, b: string) => number, boolean>
type Result1 = (a: number, b: string, x: boolean) => number

type Case2 = AppendArgument<() => void, undefined>
type Result2 = (x: undefined) => void

type cases = [
  Expect<Equal<Case1, Result1>>,
  Expect<Equal<Case2, Result2>>,
  // @ts-expect-error
  AppendArgument<unknown, undefined>,
]

// ============= Your Code Here =============
type AppendArgument<T extends (...args: any[]) => unknown, U> =
  (...args: [...Parameters<T>, U]) => ReturnType<T>

类型约束

使用T extends (...args: any[]) => unknownT进行约束,确保T是一个可调用函数

内置类型工具

  • Parameters:这是一个内置的类型工具,它接受一个函数类型T作为参数,并返回一个包含该函数所有参数类型的元组类型。它在 TypeScript 中的定义如下:
/**
 * Obtain the parameters of a function type in a tuple
 */
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
  • ReturnType:这是一个内置的类型工具,它接受一个函数类型T作为参数,并返回该函数的返回类型。它在 TypeScript 中的定义如下:
/**
 * Obtain the return type of a function type
 */
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

实现逻辑

  • Parameters<T>:获取T的参数列表
  • [...Parameters<T>, U]:将T的参数列表与U合并,形成新的参数列表
  • ReturnType<T>:获取T的返回类型
  • (...args: [...Parameters<T>, U]) => ReturnType<T>:定义一个新的函数类型,其参数列表为T的参数列表加上U,返回类型为T的返回类型