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

问题描述

我有一个type,用于将T中存在的键投影到公用键及其在U中存在的类型:

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],V> | undefined
  : never
  : never
};

IntersectByCommonKey Playground Link

K中每个键U的位置,如果T具有相同的键K,并且类型为K extends V包括该键的形状,否则为never

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

删除顶级密钥很容易:

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的计算移到了该类型的参数列表中。我们也可以将其定义为单独的类型。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...