可以基于条件从现有接口创建新接口,并删除某些顶层属性吗?

huangapple go评论64阅读模式
英文:

Is it possible to create a new interface, from an existing interface, with certain top level properties removed based on a condition?

问题

我有以下的接口:

interface Example {
  '/api/good/path': {
    get: Record<string, unknown>;
    parameters: Record<string, unknown>;
  };
  '/api/alsogood/path': {
    get: Record<string, unknown>;
  };
  '/api/bad/path': {
    post: Record<string, unknown>;
  };
  '/api/technicallygood/path': {
    get: Record<string, unknown>;
    post: Record<string, unknown>;
  };
}

是否可以从 Example 创建一个新的接口,但删除所有不包含 get 属性的嵌套对象?

我的目标是得到类似于以下的内容:

interface Example {
  '/api/good/path': {
    get: Record<string, unknown>;
    parameters: Record<string, unknown>;
  };
  '/api/alsogood/path': {
    get: Record<string, unknown>;
  };
  '/api/technicallygood/path': {
    get: Record<string, unknown>;
    post: Record<string, unknown>;
  };
}

换句话说,因为 Example['/api/bad/path'] 不包含 get,所以它被移除了。所有其他的 Example 键保留,因为它们至少包含一个名为 get 的属性。

英文:

I have the following interface:

interface Example {
  &#39;/api/good/path&#39;: {
    get: Record&lt;string, unknown&gt;;
    parameters: Record&lt;string, unknown&gt;;
  };
  &#39;/api/alsogood/path&#39;: {
    get: Record&lt;string, unknown&gt;;
  };
  &#39;/api/bad/path&#39;: {
    post: Record&lt;string, unknown&gt;;
  };
  &#39;/api/technicallygood/path&#39;: {
    get: Record&lt;string, unknown&gt;;
    post: Record&lt;string, unknown&gt;;
  };
}

Is it possible to create a new interface from Example, but removing all the nested objects that don't contain a get property?

My goal is to end up with something like:

interface Example {
  &#39;/api/good/path&#39;: {
    get: Record&lt;string, unknown&gt;;
    parameters: Record&lt;string, unknown&gt;;
  };
  &#39;/api/alsogood/path&#39;: {
    get: Record&lt;string, unknown&gt;;
  };
  &#39;/api/technicallygood/path&#39;: {
    get: Record&lt;string, unknown&gt;;
    post: Record&lt;string, unknown&gt;;
  };
}

In other words, since Example[&#39;/api/bad/path&#39;] did not contain a get, it was removed. All the other keys of Example remain, because they contain at least one property called get.

答案1

得分: 3

可以通过使用 映射类型键重映 来实现这一点。

type RemoveBadEndpoints&lt;T&gt; = {
  [K in keyof T as &#39;get&#39; extends keyof T[K] ? K : never]: T[K];
};

解释:

我们遍历键,如果属性具有 'get' 属性,我们将 K 用作键,否则,never 将会移除此属性,因为 never 不能用作键并被视为空联合类型。

type GoodEndpoints = RemoveBadEndpoints&lt;Example&gt;;

播放区

英文:

This can be achieved by using mapped types and key remapping.

type RemoveBadEndpoints&lt;T&gt; = {
  [K in keyof T as &#39;get&#39; extends keyof T[K] ? K : never]: T[K];
};

Explanation:

We map through the keys, and if the property has the 'get' property, we use K as a key, otherwise, never will remove this property since never can't be used as a key and is considered as an empty union.

// type GoodEndpoints = {
//   &#39;/api/good/path&#39;: {
//       get: Record&lt;string, unknown&gt;;
//       parameters: Record&lt;string, unknown&gt;;
//   };
//   &#39;/api/alsogood/path&#39;: {
//       get: Record&lt;string, unknown&gt;;
//   };
//   &#39;/api/technicallygood/path&#39;: {
//       get: Record&lt;string, unknown&gt;;
//       post: Record&lt;string, unknown&gt;;
//   };
// }
type GoodEndpoints = RemoveBadEndpoints&lt;Example&gt;;

playground

huangapple
  • 本文由 发表于 2023年5月22日 03:43:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76301638.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定