如何在 TypeScript 中引用除第一个参数之外的所有参数?

问题描述 投票:0回答:4

我想在另一个函数中引用一个函数的参数类型,但只使用其中的一个子集。

//params of bar should be same as foo, except p1 should be a different type

function foo(p1: string, p2: number, p3: boolean){
 ...
}

//i'd like to do something like this, though it's obviously not valid syntax
function bar(p1: string[], ...rest: Parameters<typeof foo>.slice(1)){
}

有办法做到这一点吗?显然,仅用 3 个参数手动完成并不难,但在我的实际代码中,我有更多参数,我不想重复它们。

typescript
4个回答
28
投票

TypeScript 4.0 +

选项 1:可变参数元组

type DropFirst<T extends unknown[]> = T extends [any, ...infer U] ? U : never

function bar(p1: string[], ...rest: DropFirst<Parameters<typeof foo>>) { }
// bar: (p1: string[], p2: number, p3: boolean) => void

推断除第一个元组元素之外的所有元组元素的语法现在变得更简单。请参阅 Robby Cornelissen 的 answer 了解版本 < 4.0.

选项 2:带标签的元组元素

type CommonParams = [p2: number, p3: boolean];

function foo2(p1: string, ...rest: CommonParams){} 
// foo2: (p1: string, p2: number, p3: boolean) => void
function bar2(p1: string[], ...rest: CommonParams) { }
// bar2: (p1: string[], p2: number, p3: boolean) => void

命名元组可用于保留函数参数名称,因此不存在有损转换。

游乐场


6
投票

您可以使用

Parameters
实用程序类型创建一个类型元组,然后从中创建一个新类型,忽略第一个类型:

type Rest<T extends any[]> = 
  ((...p: T) => void) extends ((p1: infer P1, ...rest: infer R) => void) ? R : never;

function foo(p1: string, p2: number, p3: boolean) {
}

function bar(p1: string[], ...rest: Rest<Parameters<typeof foo>>) {
}


bar([''], 0, true); // ok
bar('', 0, true); // error
bar([''], true, 0); // error

另请参阅此答案


1
投票

您将使用解构对象参数。 通过将对象传递到函数中,您可以选择仅使用该参数对象的字段的子集。

您可以单独定义参数接口类型(如下面的

foo
所示),也可以内联定义它(如下面的
bar
所示)。

然后,您可以将相同的对象(包含参数作为字段)传递给两者,并且函数只会选择它们需要的内容。

type FooParameters = { p1: string, p2: number, p3: boolean }
function foo({ p1, p2, p3 }: FooParameters) {
  console.log("From foo:", p1, p2, p3)
}

//i'd like to do something like this, though it's obviously not valid syntax
function bar({ p1 }: { p1: string }) {
  console.log("From bar:", p1)
}

const parameters = { p1: "First Parameter", p2: 2, p3: false }

foo(parameters)
bar(parameters)

1
投票

最简单的方法是共享剩余参数类型:

type SharedParams = [number, boolean];

//params of bar should be same as foo, except p1 should be a different type

function foo(p1: string, [p2, p3]: SharedParams){
    ...
}

//i'd like to do something like this, though it's obviously not valid syntax
function bar(p1: string[], ...rest: SharedParams){
    ...
}

游乐场

© www.soinside.com 2019 - 2024. All rights reserved.