You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中实现递归按联合类型省略的类型工具?

实现TypeScript递归类型工具OmitRecursiveByType<T, P>

下面是满足需求的递归类型工具实现,它会递归处理嵌套对象:移除类型属于指定联合类型P的属性;对于联合类型属性,移除属于P的分支,仅保留剩余类型;若属性处理后变为never则直接移除该属性。

type OmitRecursiveByType<T, P> =
  // 若当前类型属于P的成员,直接标记为never(后续会被移除)
  T extends P ? never :
  // 处理数组类型:递归处理数组元素
  T extends Array<infer U> ? Array<OmitRecursiveByType<U, P>> :
  // 处理对象类型:遍历所有键,仅保留处理后类型不为never的属性
  T extends object ? {
    [K in keyof T as OmitRecursiveByType<T[K], P> extends never ? never : K]: OmitRecursiveByType<T[K], P>
  } :
  // 原始类型(非对象、非数组)直接保留
  T;

实现逻辑说明

  1. 联合类型处理:通过T extends P ? never : ...直接过滤掉属于P的联合分支;
  2. 数组处理:通过类型推断获取数组元素类型U,递归处理后重新构造数组类型;
  3. 对象处理:遍历对象的每个键,先递归处理属性类型,若处理结果为never则移除该键,否则保留键并设置处理后的类型;
  4. 原始类型:直接保留,不做处理。

示例场景

示例1:移除嵌套对象中指定类型的属性

type UserProfile = {
  name: string;
  age: number;
  isActive: boolean;
  meta: {
    createdAt: string;
    updatedAt: number;
    flag: boolean;
  }
};

// 移除所有string类型的属性
type ProfileWithoutStrings = OmitRecursiveByType<UserProfile, string>;
// 最终类型:
// {
//   age: number;
//   isActive: boolean;
//   meta: {
//     updatedAt: number;
//     flag: boolean;
//   }
// }

示例2:处理含联合类型的属性

type Item = {
  id: string | number;
  status: 'active' | 'inactive' | boolean;
  data: {
    value: number | null | string;
    tags: Array<string | number | boolean>;
  }
};

// 移除string和boolean类型的分支/属性
type FilteredItem = OmitRecursiveByType<Item, string | boolean>;
// 最终类型:
// {
//   id: number;
//   data: {
//     value: number | null;
//     tags: Array<number>;
//   }
// }
// 注:status属性处理后变为never,因此被移除

示例3:递归处理嵌套数组和对象

type AppData = {
  user: {
    name: string;
    contacts: Array<{
      type: 'email' | 'phone';
      value: string;
      isPrimary: boolean;
    }>;
    settings: {
      darkMode: boolean;
      language: 'en' | 'fr' | number;
    }
  };
  timestamp: number;
  notes: string | null;
};

// 移除所有boolean类型的属性
type DataWithoutBooleans = OmitRecursiveByType<AppData, boolean>;
// 最终类型:
// {
//   user: {
//     name: string;
//     contacts: Array<{
//       type: 'email' | 'phone';
//       value: string;
//     }>;
//     settings: {
//       language: 'en' | 'fr' | number;
//     }
//   };
//   timestamp: number;
//   notes: string | null;
// }

示例4:处理对象联合类型

type Entity = { a: string } | { b: number } | { c: boolean };

// 移除所有包含string类型属性的对象分支
type FilteredEntity = OmitRecursiveByType<Entity, string>;
// 最终类型:{ b: number } | { c: boolean }

内容的提问来源于stack exchange,提问作者saroro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 18:20:14