# 191-追加参数

# 题目描述

实现一个泛型 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

# 分析

这一题的入参是两个,一个是函数,一个是 新增的参数类型,刨除函数不考虑的话,其实可以看成是给 元组(函数原来的参数)增加一个元素(新传入的类型)。

元组新增这个简单,可以参考 实现 Push

那么问题就转换成,对原来的函数参数进行推断后,添加新的入参类型并进行返回。

推断函数参数这个我们也做过,参考 实现 Parameters

同时还需要推断函数原本的返回参数并作为新函数的返回,这个我们也做过,参考 实现 ReturnType

三者结合,其实就可以得到本题的一种答案。

type Push<T extends any[], U> = [...T, U];
type Parameters<T extends (...args: any) => any> = T extends (
  ...args: infer P
) => any
  ? P
  : never;
type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

type AppendArgument<Fn extends (...args: any) => any, P> = (
  ...args: Push<Parameters<Fn>, P>
) => MyReturnType<Fn>;

当然,这么写也太麻烦了,入参的推断和返回值的推断也略显冗余,可以合并到一起。此时可以看最终的题解

# 题解

type AppendArgument<Fn extends Function, A> =
  // 推断入参和返回值
  Fn extends (...args: infer P) => infer R
    ? // 生成新的入参和返回值
      (...args: [...P, A]) => R
    : never;

其实本质和上面三者结合是一样的,只不过此处合并到一起,看起来简单一点

# 知识点

  1. 实现 Push
  2. 实现 Parameters
  3. 实现 ReturnType
Last Updated: 2023/5/16 06:00:28