Typescript 类型体操 —— Change Argument

941 阅读1分钟

🤔要求

实现一个范型 ChangeArgument<Fn extends (...args: any[]) => any[]>,对于给定的函数类型 Fn, 返回一个新的函数 G

G的参数类型为Fn参数类型减去第一项FirstG的返回类型为Fn的返回类型在末尾加上类型为First的值

  type Fn = (a: number, b: string) => [number]
  type Result = ChangeArgument<Fn> 
  // 期望Result是 (a: number) => [number, string]
  type Fn = () => [number]
  type Result = ChangeArgument<Fn> 
  // 期望Result是 () => [number]

📖知识点

  1. infer 最早出现在此 PR 中,表示在 extends 条件语句中待推断的类型变量。
  2. Tuple types allow you to express an array with a fixed number of elements whose types are known, but need not be the same. For example, you may want to represent a value as a pair of a string and a number:
  3. TypeScript, like JavaScript, allows you to work with arrays of values. Array types can be written in one of two ways. In the first, you use the type of the elements followed by [] to denote an array of that element type:
  4. When a rest parameter has a tuple type, the tuple type is expanded into a sequence of discrete parameters. For example the following two declarations are equivalent:
  5. When a function call includes a spread expression of a tuple type as the last argument, the spread expression corresponds to a sequence of discrete arguments of the tuple element types.

🔗知识链接

  1. 知识点: infer
  2. 知识点: tuple 和 Array
  3. 知识点 : rest Parameters 和 spread expression
  4. 知识点: 获取数组长度

😢问题 & 解答

  1. Change-Argument
  2. 解答

🍗场景

type FirstArgument<T extends (...args: any[]) => any> = Parameters<T>[0]
type RestArgument<T extends (...args: any[]) => any> = 
    Parameters<T> extends [ first: any, ...rest: infer R ] ? R : []; 
const bindFunction = <T extends (...args: any[]) => any,>(fn: T, firstArgs: FirstArgument<T>) => {
    return (...restArgs: RestArgument<T>) => {
        fn(firstArgs, ...restArgs)
    }

}
const demo = bindFunction((name: string, age: number) => { console.log(name + age)}, "123")
demo(123)