Typescript 函数接受字符串数组并返回以给定字符串作为键的对象

use*_*765 3 typescript typescript-generics

如何正确地编写以下方法:

const getVars = (vars: string[]) => {
  const data = [
    {
      "someId": "28",
      "someAttr": "2",
    },
    {
      "someId": "43",
      "someOtherAttr": "3",
    },
    {
      "someOtherId": "32",
      "someAttr": "4",
    }
  ] // an array containing some data

  const result = vars.reduce((acc, _var) => ({
    ...acc,
    ...data.reduce((acc, acc) => ({
      ...acc,
      [...acc[_var], curr[_var]]
    }, {})
  }), {})

  return result
}
Run Code Online (Sandbox Code Playgroud)

用法:

const { someId, someAttr } = getVars(['someId', 'someAttr'])
Run Code Online (Sandbox Code Playgroud)

输出: someId: ['28', '43'], someAttr: ['2', '4']

我想要打字稿,getVars以便返回类型反映给定的参数,例如,如果我传递 ['someId'] 作为参数,打字稿就会知道该函数返回一个带有键“someId”的对象。

Lin*_*ste 6

您可以严格或非常严格地输入这种类型。这取决于你预先了解多少信息(你知道元素的关键吗data?)以及你想要有多疯狂。你data这里是一个带有钥匙的arrayof objects string。价值观总是吗string?或者他们只是碰巧出现在这个例子中?

对于有点严格的方法,我假设值总是string并且data类型为Record<string, string>[]

我们想知道传递给的特定字符串值getVars,因此我们将使用泛型T extends string。我们返回一个对象,该对象以这些特定字符串T作为键,值是字符串数组。所以返回类型是Record<T, string[]>.

当您通过构建对象时,reduce()需要使用as来断言最终对象的类型。

const getVars = <T extends string>(vars: T[]): Record<T, string[]> => {
    return vars.reduce((acc, _var) => ({
        ...acc,
        [_var]: data.map(o => o[_var]).filter(v => v !== undefined)
    }), {} as Record<T, string[]>);
}

const { someId, someAttr } = getVars(['someId', 'someAttr'])
console.log(someId, someAttr);
Run Code Online (Sandbox Code Playgroud)

Typescript Playground 链接