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

TypeScript类型交集处理:移除可选属性的| undefined标识

解决TypeScript类型交集展开后可选属性带| undefined的问题

问题描述

当合并两个接口的交集类型并展开为对象时,希望可选属性仅显示?: boolean而非?: boolean | undefined:

interface ISelect {
    selectOnly?: boolean
}
interface IDefault {
    defaultValue: string
}

// 原始交集类型
type BothTypes = ISelect & IDefault

期望鼠标悬停BothTypes时的显示效果:

(alias) type BothTypes = {
    selectOnly?: boolean;
    defaultValue: string;
}

已尝试方案

使用基础映射类型展开交集,但可选属性会自动带上| undefined:

type Resolve<T> = {
    [P in keyof T]: T[P]
}
type BothTypes = Resolve<ISelect & IDefault>

实际得到的结果:

(alias) type BothTypes = {
    selectOnly?: boolean | undefined;
    defaultValue: string;
}

尝试用Exclude移除undefined也无效:

type Resolve<T> = {
    [P in keyof T]: Exclude<T[P], undefined>
}

解决方案

通过区分类型中的可选键和必选键,分别处理后再合并,可以实现预期效果:

// 提取类型中的可选键
type OptionalKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? K : never }[keyof T];
// 提取类型中的必选键
type RequiredKeys<T> = Exclude<keyof T, OptionalKeys<T>>;

// 自定义Resolve类型,处理可选属性的undefined问题
type Resolve<T> = 
  // 保留必选属性的原始类型
  Pick<{ [K in RequiredKeys<T>]: T[K] }, RequiredKeys<T>> &
  // 处理可选属性:移除undefined并保持可选性
  Partial<{ [K in OptionalKeys<T>]: Exclude<T[K], undefined> }> extends infer O
  ? { [K in keyof O]: O[K] } // 展开合并后的交集为对象
  : never;

测试示例

interface ISelect {
    selectOnly?: boolean
}
interface IDefault {
    defaultValue: string
}

type BothTypes = Resolve<ISelect & IDefault>;

此时鼠标悬停BothTypes,会显示预期的格式:

(alias) type BothTypes = {
    selectOnly?: boolean;
    defaultValue: string;
}

原理说明

  1. OptionalKeys<T>:通过-?移除可选修饰符后,判断该属性是否能被空对象兼容,以此筛选出原始类型中的可选键。
  2. RequiredKeys<T>:从所有键中排除可选键,得到必选键集合。
  3. Resolve<T>:将必选属性直接保留,可选属性则通过Partial维持可选性,同时用Exclude<T[K], undefined>移除多余的undefined类型,最后通过类型推断展开交集为扁平对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 18:55:23