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

如何让TypeScript类型所有键为必填,同时保留undefined可选值?

TypeScript中实现特定的类型映射需求

需求规则

需要将类型的键值对按以下规则映射:

  • required_key: string | undefined 保持为 required_key: string | undefined(不变)
  • required_key: string 保持为 required_key: string(不变)
  • optional_key?: string | undefined 转为 optional_key: string | undefined(移除键的?)
  • optional_key?: string 转为 optional_key: string | undefined(移除键的?并添加undefined作为可选值)

示例问题

给定如下接口:

interface Person {
  firstName: string | undefined;
  middleName?: string;
  lastName?: string | undefined;
}

期望转换后的类型为:

interface Person {
  firstName: string | undefined;
  middleName: string | undefined;
  lastName: string | undefined;
}

但使用常规的-?操作符实现的Normalize类型无法满足需求:

type Normalize<T> = { [K in keyof T]-?: T[K] };

// 使用Normalize<Person>得到的结果:
// interface Person {
//   firstName: string | undefined;
//   middleName: string;
//   lastName: string;
// }

const test: Normalize<Person> = {
  firstName: undefined,
  middleName: undefined, // TypeScript错误:类型为string,不允许undefined
  lastName: undefined, // TypeScript错误:类型为string,不允许undefined
};

问题在于-?操作符会同时移除键的可选性和值类型中的undefined,需要找到方法为原可选键重新添加undefined值选项。

解决方案

可以通过自定义条件类型实现需求,核心思路是先识别出原类型中的可选键,再对这些键的类型手动添加undefined,同时移除所有键的可选性:

// 提取类型中的所有可选键
type OptionalKeys<T> = { 
  [K in keyof T]: T extends { [P in K]-?: T[P] } ? never : K 
}[keyof T];

// 实现需求的Normalize类型
type Normalize<T> = {
  [K in keyof T]-?: K extends OptionalKeys<T> ? T[K] | undefined : T[K]
};

测试上述类型:

interface Person {
  firstName: string | undefined;
  middleName?: string;
  lastName?: string | undefined;
}

type NormalizedPerson = Normalize<Person>;
// 结果符合预期:
// interface NormalizedPerson {
//   firstName: string | undefined;
//   middleName: string | undefined;
//   lastName: string | undefined;
// }

const test: NormalizedPerson = {
  firstName: undefined,
  middleName: undefined, // 无错误
  lastName: undefined, // 无错误
};

原理说明

  1. OptionalKeys<T>通过条件类型判断每个键是否为可选:如果将键K转为必填后,原类型T不再能赋值给这个新类型,说明K原本是可选键。
  2. Normalize<T>中,对每个键K先通过-?移除可选性,再判断K是否属于可选键:如果是,则将值类型设置为T[K] | undefined;否则保持原类型不变。

这样既移除了所有键的可选标记,又确保原可选键的类型包含undefined,完全符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:00:38