
本教程旨在解决在 typescript 中定义对象类型时遇到的一个常见问题:如何确保对象的键来源于一个预定义的集合,但同时允许这些键是可选的,而非全部强制存在。文章将深入探讨如何结合使用映射类型(mapped types)和可选修饰符(?),以创建灵活且类型安全的对象结构,从而避免因缺少非必需属性而导致的编译错误。
在 TypeScript 开发中,我们经常需要定义具有特定结构的对象,其中对象的键值(key)必须限定在某个预设的枚举或字符串集合中。然而,一个常见的挑战是,我们可能不希望对象必须包含该集合中的所有键,而是允许它们是可选的。本文将详细介绍如何利用 TypeScript 的映射类型(Mapped Types)和可选修饰符(Mapping Modifiers)来优雅地解决这一问题。
首先,我们定义两个常量对象,它们将作为我们对象键的来源。使用 as const 可以确保 TypeScript 推断出最窄的字面量类型,而不是宽泛的 string 类型。
export const ABC = {
A: 'A',
B: 'B',
C: 'C',
} as const;
export const DEF = {
D: 'D',
E: 'E',
F: 'F',
} as const;接下来,我们基于这些常量对象创建联合类型(Union Types),这些联合类型将精确地表示允许的键值。
export type AbcTypes = (typeof ABC)[keyof typeof ABC]; // 类型为 'A' | 'B' | 'C' export type DefTypes = (typeof DEF)[keyof typeof DEF]; // 类型为 'D' | 'E' | 'F'
AbcTypes 和 DefTypes 现在分别是 ABC 和 DEF 对象中所有值组成的字面量联合类型。
我们的目标是创建一个字典类型 MyNewDictionary,它的第一层键来自 AbcTypes,第二层键来自 DefTypes。每个最内层对象都包含 onClick 和 onCancel 两个函数。
一种直观的定义方式是使用映射类型:
type MyNewDictionaryAttempt = {
[pKey in AbcTypes]: {
[eKey in DefTypes]: {
onClick: () => void;
onCancel: () => void;
}
}
};然而,当我们尝试创建一个 MyNewDictionaryAttempt 类型的对象实例,并且只赋值了部分键时,TypeScript 编译器会报错:
度加剪辑
度加剪辑(原度咔剪辑),百度旗下AI创作工具
380
查看详情
const dictionaryAttempt: MyNewDictionaryAttempt = {
[ABC.A]: {
[DEF.D]: {
onClick: () => null,
onCancel: () => null,
}
}
};
/*
错误示例:
Type '{ D: { o
nClick: () => null; onCancel: () => null; }; }' is missing the following properties from type '{ D: { onClick: () => void; onCancel: () => void; }; E: { onClick: () => void; onCancel: () => void; }; F: { onClick: () => void; onCancel: () => void; }; }'
*/这个错误表明,尽管我们只为 ABC.A 下的 DEF.D 属性赋了值,但 MyNewDictionaryAttempt 类型要求 ABC.A 下必须包含 DEF.E 和 DEF.F,同样,整个 dictionaryAttempt 对象也必须包含 ABC.B 和 ABC.C。这是因为默认情况下,映射类型会创建所有属性都为必需(mandatory)的新类型。
要解决这个问题,我们需要引入 TypeScript 的映射修饰符(Mapping Modifiers)。具体来说,使用 ? 修饰符可以将映射类型生成的属性标记为可选(optional)。
我们将 MyNewDictionaryAttempt 类型修改为 MyNewDictionary,在每个映射类型的键后面添加 ?:
type MyNewDictionary = {
[pKey in AbcTypes]?: { // 外层键现在是可选的
[eKey in DefTypes]?: { // 内层键现在也是可选的
onClick: () => void;
onCancel: () => void;
}
}
};通过在 [pKey in AbcTypes] 和 [eKey in DefTypes] 后面分别添加 ?,我们告诉 TypeScript:
现在,我们可以按照预期创建对象实例,只包含我们需要的属性,而不会引发编译错误:
const dictionary: MyNewDictionary = {
[ABC.A]: {
[DEF.D]: {
onClick: () => console.log('A.D clicked'),
onCancel: () => console.log('A.D cancelled'),
},
// DEF.E 和 DEF.F 在这里是可选的,可以不写
},
[ABC.C]: { // ABC.B 也是可选的,可以不写
[DEF.F]: {
onClick: () => console.log('C.F clicked'),
onCancel: () => console.log('C.F cancelled'),
}
}
};
// 尝试访问存在的属性
if (dictionary[ABC.A]?.[DEF.D]) {
dictionary[ABC.A][DEF.D]?.onClick(); // 输出: A.D clicked
}
// 尝试访问不存在的属性(类型安全地处理 undefined)
console.log(dictionary[ABC.B]?.D?.onClick); // 输出: undefined通过掌握映射类型和可选修饰符,你可以在 TypeScript 中创建出更加灵活、健壮且类型安全的对象结构,有效管理复杂的配置或数据字典,同时避免不必要的强制性属性检查。
以上就是TypeScript教程:使用映射类型和可选修饰符定义具有受限且可选键的对象的详细内容,更多请关注其它相关文章!
# 不写
# 栾城网站推广效果
# 天津推广关键词排名优化
# 如何推广网站选火21星
# 鄞州区外贸推广网站优化
# 服务网站推广技术
# 网站建设的功能定位
# 临沧营销推广咨询招聘信息
# 廊坊网站如何做推广
# 网站建设中html5
# 小企业网站优化
# 这一
# 有什么特点
# typescript
# 如何实现
# 键值
# 创建一个
# 如何使用
# 有什么关系
# 修饰符
# 可选
# typescript教程
# 编译错误
# 常见问题
# win
# app
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
高效调试PHP大型嵌套数组:JSON序列化与可视化工具实践
大众点评了却看不到是怎么回事
漫蛙manwa官网浏览入口_漫蛙漫画网页版访问链接
POKI小游戏在线免费入口链接 POKI小游戏无下载秒玩玩
win11关机几秒又自己开机 Win11关机自动重启问题修复
CDR如何复制交互式填充色
MacBook Pro词典使用指南
Python csv 模块处理非字符串数据:列表写入 CSV 文件的机制解析
在J*a中如何实现类的继承与方法重用_OOP继承方法重用技巧分享
行者app怎样导出日志
济南公交卡手机充值指南
PHP魔术方法__set与__isset:设计考量、性能权衡与静态分析的视角
易车网官网直达入口 易车网在线登录入口
实现可重用自定义Python Range类
智云Q3和Q2有什么升级_智云Q3与Q2手持云台功能与性能对比分析
iPhone14无法连接蓝牙设备如何解决
如何在Podman容器中运行Composer_Docker替代品Podman的PHP与Composer容器化实践
安居客移动经纪人怎么设置自动回复?-安居客移动经纪人设置自动回复的方法
怎样设置开机后自动运行某个程序_Windows启动文件夹与任务计划【自动化】
Golang如何使用crypto/md5生成哈希_Golang MD5哈希生成方法
B站怎么开|直播| B站|直播|申请需要什么条件【新手必看】
狙击外星人小游戏在线链接_狙击外星人小游戏网页链接
QQ邮箱手机版网页版 QQ邮箱登录入口地址
Golang如何使用gRPC拦截器实现日志收集_Golang gRPC拦截器日志收集实践
悟空浏览器网页版在线工具 悟空浏览器网页版在线平台入口
实现二叉树的层序插入:基于树大小的路径导航
win11怎么更改账户类型 Win11标准用户和管理员权限切换【教程】
抖音猜你想搜能说明对方搜过吗
胃动力不足?试试这5个调理方法
rabbitmq 持久化有什么缺点?
使用CSS :has() 选择器实现父元素样式控制:从子元素反向应用样式
《星露谷物语》克林特好感度事件介绍
服装短视频如何起号推广?服装短视频起号推广有什么要求?
抖音火山版注销账号抖音会注销吗 抖音火山版与抖音账号注销关系
招商淘客入门指南
Lar*el Dusk 测试中管理浏览器权限:以剪贴板访问为例
c++如何链接Boost库_c++准标准库的集成与使用
《崩坏:星穹铁道》3.6版本异相仲裁打法及配队推荐
动漫岛汉化官网网 动漫岛官方动漫汉化地址
Firefox OS应用开发:解决XMLHttpRequest跨域请求阻塞问题
电脑从睡眠中被自动唤醒怎么办_Windows唤醒源事件查看与禁用【解决】
嘀嗒顺风车如何开具电子发票
使用Python和NLTK从文本中高效提取名词的实用教程
Golang如何实现HTTP请求重试机制_Golang HTTP请求错误处理策略
我的世界游戏平台入口 我的世界官方官网直达链接
店铺如何做视频号推广?做视频号推广有用吗?
快递优选如何查优选物流_快递优选专属物流渠道查询与配送时效
《浙里办》电子发票开具方法
圆通快递官网入口查询单号 手机版官方查询入口
《深林》冬季章节图文攻略
2025-11-22
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。