TypeScript - 删除具有特定类型的所有属性

标签 typescript typescript-generics mapped-types

我有一个 type 用于将 T 中存在的 key 投影到 U 中存在的公共(public) key 及其类型:

type IntersectByCommonKey<T, U, V = any> = {
  [K in keyof U]: K extends keyof T ?
  T[K] extends V ?
  U[K]
  : T[K] extends object ?
  IntersectByCommonKey<T[K], U[K], V>
  : T[K] extends object | undefined ?
  IntersectByCommonKey<T[K], U[K], V> | undefined
  : never
  : never
};

IntersectByCommonKey Playground Link

对于 U 中的每个键 K,如果 T 具有相同的键 K,并且如果在 K 处键入 extends V,包括该键的形状,否则从不

对于 IntersectByCommonKey 返回的类型,我想删除所有具有 never 类型的键,这意味着它必须处理嵌套的 Record 形状也是。

删除顶级 key 非常容易:

type ExcludeKeysWithTypeOf<T, V> = {
  [K in keyof T]: Exclude<T[K], undefined> extends V ? never : K 
}[keyof T]

type Without<T, V> = Pick<T, ExcludeKeysWithTypeOf<T, V>>;

ExcludeKeysWithTypeOf Playground Link

但是,我正在努力为嵌套的 Record 实现相同的结果,有没有一种方法可以递归地删除类型为 never 的键?

最佳答案

我们需要进行递归调用以进入嵌套记录类型。 这是一个示例解决方案:

type Without<T, V, WithNevers = {
  [K in keyof T]: Exclude<T[K], undefined> extends V ? never 
  : (T[K] extends Record<string, unknown> ? Without<T[K], V> : T[K])
}> = Pick<WithNevers, {
  [K in keyof WithNevers]: WithNevers[K] extends never ? never : K
}[keyof WithNevers]>

核心思想是当我们的T[K] 将具有Record 类型时,它将递归地再次调用自身(Without 类型级函数)。整个类型将减少到所需的形式,其中每个嵌套对象都将删除我们想要的键。

整个代码片段 - the playground

注意:我将 WithNevers 的计算移到类型的参数列表中,以实现更好的可读性。我们也可以将其定义为单独的类型。

关于TypeScript - 删除具有特定类型的所有属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63447660/

相关文章:

javascript - Angular ul,cdk-virtual-scroll-viewport 列表,键盘选择

typescript - 无法从过滤类型中删除带有 never 的属性以获取剩余的键

reactjs - 当组件是通用的(多态 react 组件)时键入点击处理程序

typescript - 映射类型不是数组类型

typescript - 在 Typescript 中,我可以创建强制需要属性的映射类型吗?

typescript - 为什么在 TypeScript 中使用部分映射类型时类型保护的行为不同

node.js - 如何在 Angular2 中使用 'crypto' 模块?

typescript - 装饰器的运行顺序是什么?

reactjs - 从 string=>type 的映射推断 react Prop 类型时修复 typescript 警告

typescript - 按对象键的通用数据