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

能否基于条件为TypeScript映射类型动态应用修饰符?

动态为TypeScript映射类型字段应用修饰符的实现方案

问题描述

希望根据条件为TypeScript映射类型中的字段动态应用修饰符(例如将指定字段设为必填),尝试的代码无法合法运行:

type TestKey<T, K extends keyof T> = K extends 'b' ? true : false

type RequiredIf<T> = {
    [K in keyof T]: TestKey<T, K> extends true ? T[K]-? : T[K]
                // ^无修饰符                ^^此处应用修饰符
}

type test = RequiredIf<{a: 1, b?: 2, c?: 3}> // 期望得到 {a: 1, b: 2, c?: 3}

可行实现方案

TypeScript不支持在条件类型分支中直接使用-?这类修饰符操作,但可以通过内置工具类型组合或映射类型交叉来实现需求,以下是两种常用方案:

方案一:Pick + Required + Omit 组合

通过提取需要设为必填的字段,用Required处理后再与原类型的剩余字段合并:

type TestKey<T, K extends keyof T> = K extends 'b' ? true : false;

// 筛选出需要设为必填的键
type RequiredKeys<T> = { 
  [K in keyof T]: TestKey<T, K> extends true ? K : never 
}[keyof T];

type RequiredIf<T> = Omit<T, RequiredKeys<T>> & Required<Pick<T, RequiredKeys<T>>>;

type test = RequiredIf<{a: 1, b?: 2, c?: 3}>; // 结果:{a: 1, b: 2, c?: 3}

方案二:映射类型交叉覆盖

利用交叉类型中必填属性覆盖可选属性的特性,单独处理需要设为必填的字段:

type TestKey<T, K extends keyof T> = K extends 'b' ? true : false;

type RequiredIf<T> = {
  [K in keyof T]: T[K]
} & {
  // 仅对符合条件的字段移除可选性
  [K in keyof T as TestKey<T, K> extends true ? K : never]-?: T[K]
};

type test = RequiredIf<{a: 1, b?: 2, c?: 3}>; // 结果:{a: 1, b: 2, c?: 3}

是否需要提交功能请求?

当前通过内置工具类型的组合已经能覆盖这类动态修饰符需求,虽然写法不如直接在类型分支中添加修饰符直观,但足够满足大多数场景。如果有更复杂的动态修饰需求(例如同时动态控制readonly和可选性的复杂场景),可以考虑向TypeScript官方提交功能请求,但针对当前的单一需求,必要性不高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 06:05:06