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

如何优化TypeScript中将T | undefined类型键转为可选键的实现?

如何优化将含undefined的联合类型键转为可选键的TypeScript类型工具?

问题背景

你想要实现一个类型转换器,接收任意继承Record<string, any>的类型,把其中类型为T | undefined的键转为可选键,其余键保持必填。你的示例需求很清晰:

// 输入类型
type WithUndefined = {
  a: string,
  b: number | undefined,
  c: boolean | undefined,
};

// 期望输出类型
type WithoutUndefined = {
  a: string,
  b?: number,
  c?: boolean,
}

但你当前的实现拆分了多个辅助类型(OnlyKeepsDefined、OnlyKeepsUndefined、RemoveUnionUndefined),不仅代码冗余,还导致VSCode无法在悬浮提示中解析最终类型,完全违背了提升可读性的初衷。


优化后的简洁实现

我们可以利用TypeScript的映射类型条件判断和交叉类型合并,用更紧凑的代码实现需求,同时保证编辑器能正确解析最终类型:

type UndefinedToOptional<T extends Record<string, any>> = 
  // 处理必填键:保留不含undefined的键和原类型
  { [K in keyof T as undefined extends T[K] ? never : K]: T[K] } & 
  // 处理可选键:提取含undefined的键,转为可选并移除undefined类型
  { [K in keyof T as undefined extends T[K] ? K : never]?: Exclude<T[K], undefined> } 
  // 交叉后重新映射为一个干净的对象类型,让编辑器能正确显示
  extends infer O ? { [K in keyof O]: O[K] } : never;

代码解释

  1. 必填键处理:第一个映射类型通过条件判断,只保留那些类型中不包含undefined的键,保持它们的必填状态和原类型。
  2. 可选键处理:第二个映射类型提取类型中包含undefined的键,将它们标记为可选(?),同时用Exclude<T[K], undefined>移除类型中的undefined。
  3. 合并为干净类型:通过infer和重新映射,把交叉后的类型合并成一个单一的对象类型,这样VSCode的悬浮提示就能正确显示最终的结构,而不是显示交叉类型的原始形式。

测试验证

用你提供的测试类型验证:

type TestType = {
  a: string;
  b: number | undefined;
  c: undefined;
};

type FilteredTestType = UndefinedToOptional<TestType>;
// 编辑器悬浮提示会显示清晰的最终类型:
// {
//   a: string;
//   b?: number;
//   c?: never;
// }

对应的合法赋值依然全部有效:

const a: FilteredTestType = { a: "a" }; 
const b: FilteredTestType = { a: "a", b: 1 };
const c: FilteredTestType = { a: "a", b: 1, c: undefined };

对比优势

和你原来的实现相比,这个优化版本:

  • 代码更紧凑,不需要拆分多个辅助类型,可读性更强
  • 编辑器能正确解析并显示最终的类型结构,符合你提升可读性的初衷
  • 逻辑更直观,直接拆分必填和可选两部分处理,容易理解

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 16:25:16