映射的元组类型/数组:将数组作为元组传递给函数

时间:2019-09-18 10:21:32

标签: typescript mapped-types

我想做的是将一个数组传递给一个函数,并在另一个函数中将该数组的值作为元组接收。

myFunction(
    (a, b) => null,
    {
        params: [true, 1]
    }
);

在上面的示例中,我要输入:a: booleanb: number。相反,我收到a: boolean | numberb: boolean | number

请记住,我希望参数的长度可变。 [1, false, 'string', {}]也应该是可能的。

如我所读,这与mapped tuples有关系吗?但是我真的不明白。

我当前的实现如下:

function myFunction<P extends any[]>(
    fn: (...params: P) => null, 
    options: { params: P }) {
    ...
}

-

这实际上是有效的:

myFunction(
    (a, b) => null,
    {
        params: [true, 1] as [boolean, number]
    }
);

但是我真的不想一直都进行类型转换以使其正常工作:/

3 个答案:

答案 0 :(得分:1)

更新:

实际上有一种更简单的方法。通常,只有使用as const的函数调用者才能将数组缩小为元组类型(请参阅原始答案)。我们可以通过including a tuple type as constituent of an uniontype将这一责任移到函数P的泛型类型参数myFunction上,因此约束现在变成P extends (ReadonlyArray<any> | readonly [any])

function myFunction<P extends (ReadonlyArray<any> | readonly [any])>(
  fn: (...params: P) => null,
  options: { params: P }
) {
  fn(...options.params)
  // ...
}

myFunction((a, b) => null, {
  params: [true, 1]
});

// params: [boolean, number]
// fn: (a: boolean, b: number) => null

Playground

jcalz的信用归answer所用,涉及一些“巫术代码” code我在这里捡到了。还可以查看相关的feature suggestion

原始答案:

尽管我不太了解您的用例,但是呢?

// fn: (params_0: true, params_1: 1, params_2: Date) => null
myFunction((a, b) => null, {
  params: ([true, 1, new Date()]) as const
}); 

function myFunction<P extends readonly any[]>(
  fn: (...params: P) => null,
  options: { params: P }
) { fn(...options.params); }

您仍然使用const assertion,但不必手动编写所有元组项类型。我认为,您只是将params直接传递给回调函数,因为将无法依靠某种依赖元组项类型的方式在P主体中操纵myFunction ,因为P仅限于扩展any[]

通常,如果您在初始化时不使用Array缩小数组的大小,则编译器会将它们初始化为as const类型。

const options = {
  params: [3,4,"a"] // params: (string | number)[];
}

const optionsConst = {
  params: [3,4,"a"] as const // params: readonly [3, 4, "a"];
}

Playground

答案 1 :(得分:0)

您的声明代码正确。

这是调用函数的正确方法:

myFunction<[number, boolean]>(
  (a, b) => null, 
  {params: [1, true]}
);

答案 2 :(得分:0)

尝试一下:

function myFunction<A, B, P extends [A, B]>(
  fn: (...params: P) => null,
  options: { params: P }) {
     ...
}