在 TypeScript 中按类型排除函数参数

Excluding function parameters by type in TypeScript

我希望能够采用具有 n 个参数的函数和 return 基于该函数的类型,其中类型为 x 的任何参数不再属于函数类型。例如:

function myTestFunction(email: string, context: TestContext, password: string): void {
  ...
}

我想要一个类型来创建这样的函数定义:

function myTestFunction(email: string, password: string): void {
  ...
}

我已经成功做到了:

type Filter<T> = T extends [] 
  ? [] 
  : T extends [infer A, ...infer B] 
    ? A extends TestContext 
      ? Filter<B>
      : [A, ...Filter<B>]
    : T;
type ConvertFunction<T> = T extends (...args: any[]) => any
  ? (...args: Filter<Parameters<T>>) => ReturnType<T>
  : T;

唯一的问题是参数名称丢失,签名变为:

function myTestFunction(args_0: string, args_1: string): void {
  ...
}

请问如何在不丢失参数名称的情况下执行此操作?

嗯,我认为你做不到。

你可以做的是传播一个元组来保存名字

type MyTup = [a: string, b: number]
type MyTup2 = [...MyTup] // [a: string, b: number]

但是,当您从 Tuple 中获取单个值时,它将失去其名称。

type MyTup = [a: string, b: number]
type MyTup2 = [MyTup[0], MyTup[1] // [string, string]

并且如果您将未命名的成员与命名的元组合并,则所有成员都将变为未命名的:

type MyTup = [a: string, b: number]
type B = [MyTup[0], ...MyTup] // [string, string, string]

当然,您可以重新添加名称,但据我所知,无法真正获取元组成员的名称。所以没有办法通用地做到这一点。

type B = [asdf: MyTup[0], qwerty: MyTup[1]] // [asdf: string, qwerty: string]

这意味着当你这样做时:

[A, Filter<B>]

那么你正在生成一个未命名的元组。而这种重新构造元组的递归方式,是目前唯一通用的增减元组成员的方法。


所以我可能是错的,但我不确定当前版本的打字稿是否可行。