Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
773 views
in Technique[技术] by (71.8m points)

typescript - Typing recursive function removing property from object

I have a function that recursively removes a particular property from all objects. If we write it in Javascript, it would be:

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;
};

For example:

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

Would result in:

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

Any idea how I can type this? It seems like I should have enough information to be able to return a new type that somehow recursively returns the same type with the remove property omitted from any object types.

question from:https://stackoverflow.com/questions/65888383/typing-recursive-function-removing-property-from-object

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I wrote this with a generic Drop instead of just a literal string "remove" but we can set a default value for Drop as "remove".

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

T represents the entire value. At each level of the object, we want to only keep the keys which are not assignable to our Drop key generic: Exclude<keyof T, Drop>. To apply this recursively, the new value for that key must itself be filtered: Removed<T[K], Drop>. The T extends object ? {...} : T; is not actually necessary, but leads to cleaner inferred types.

Typescript Playground Link

This checks out with your sample input and output. Applying the type to your function is a mess though.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...