键入递归函数从对象中删除属性

时间:2021-01-25 16:11:39

标签: typescript typescript-generics

我有一个函数可以递归地从所有对象中删除一个特定的属性。如果我们用 Javascript 编写它,它将是:

function removeRecursive(value) {
  if (Array.isArray(value)) {
    return value.map(removeRecursive);
  }

  if (typeof value === "object") {
    return Object.keys(value)
      .filter(key => key !== "remove")
      .reduce((acc, key) => {
        acc[key] = removeRecursive(value[key]);
        return acc;
      }, {});
  }
  return value;
};

例如:

removeRecursive({
  foo: {
    bar: 'foo.bar',
    remove: 'this'
  },
  remove: 'also-this',
  list: [{
    remove: 'this-as-well',
    baz: 'baz'
  }]
})

会导致:

{
  "foo": {
    "bar": "foo.bar"
  },
  "list": [
    {
      "baz": "baz"
    }
  ]
}

知道如何输入这个吗?似乎我应该有足够的信息来返回一个新类型,该类型以某种方式递归返回相同类型,并从任何对象类型中省略 remove 属性。

1 个答案:

答案 0 :(得分:0)

我用泛型 Drop 而不是文字字符串 "remove" 写了这个,但我们可以将 Drop 的默认值设置为 "remove"

type Removed<T, Drop = "remove"> = T extends object ? {
    [K in Exclude<keyof T, Drop>]: Removed<T[K], Drop>
} : T;

T 表示整个值。在对象的每个级别,我们只想保留不可分配给我们的 Drop 键泛型:Exclude<keyof T, Drop> 的键。要递归地应用它,必须过滤该键的新值本身:Removed<T[K], Drop>T extends object ? {...} : T; 实际上不是必需的,但会导致更清晰的推断类型。

Typescript Playground Link

这会检查您的示例输入和输出。但是,将类型应用于您的函数是一团糟。