首页 > web前端 > js教程 > 正文

TypeScript 教程:在映射类型中实现可选且受限的对象键

心靈之曲
发布: 2025-11-22 15:57:18
原创
235人浏览过

TypeScript 教程:在映射类型中实现可选且受限的对象键

本教程探讨如何在 typescript 中定义一个对象类型,使其键值受限于预定义集合,同时允许这些键是可选的,而非强制。通过利用 typescript 的映射修饰符 `?`,我们能够灵活地构建嵌套对象类型,避免因缺少部分键而导致的类型错误,从而提升类型定义的灵活性和实用性。

在 TypeScript 中定义复杂的数据结构时,我们经常需要创建一种对象类型,其键名必须来自某个预定义的集合,但同时又希望这些键是可选的,即不必全部存在。这在构建配置对象、API 响应或灵活的数据字典时尤为常见。本文将深入探讨如何使用 TypeScript 的映射类型(Mapped Types)及其修饰符来优雅地解决这一问题。

1. 问题背景与初始尝试

假设我们有两组常量,分别定义了两种类型的标识符:

export const ABC = {
  A: 'A',
  B: 'B',
  C: 'C',
} as const;

export const DEF = {
  D: 'D',
  E: 'E',
  F: 'F',
} as const;

// 提取这些常量的值作为联合类型
export type AbcTypes = (typeof ABC)[keyof typeof ABC]; // 'A' | 'B' | 'C'
export type DefTypes = (typeof DEF)[keyof typeof DEF]; // 'D' | 'E' | 'F'
登录后复制

现在,我们的目标是构建一个嵌套对象 MyNewDictionary,其结构如下:

  • 第一层键必须是 AbcTypes 中的值。
  • 第二层键必须是 DefTypes 中的值。
  • 最内层对象包含 onClick 和 onCancel 两个函数。

最初的尝试可能会是这样:

type MyNewDictionary = {
  [pKey in AbcTypes]: {
    [eKey in DefTypes]: {
      onClick: () => void;
      onCancel: () => void;
    }
  }
};
登录后复制

然而,当我们尝试创建一个 MyNewDictionary 类型的实例,但只填充部分键时,TypeScript 会立即报错:

const dictionary: MyNewDictionary = {
  [ABC.A]: {
    [DEF.D]: {
      onClick: () => null,
      onCancel: () => null,
    }
  }
};
// 错误信息示例:
// Type '{ D: { onClick: () => 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; }; }': 'E', 'F'
// 并且外层也可能报错,因为缺少 'B', 'C'
登录后复制

这个错误表明,当前 MyNewDictionary 的定义强制要求所有 AbcTypes 和 DefTypes 中的键都必须存在。使用 Partial<T> 作用于整个 MyNewDictionary 类型可能无法完全解决嵌套层级的可选性问题,因为它只会使顶层属性可选,而嵌套的映射类型内部仍然是强制的。

2. 解决方案:映射修饰符 ?

TypeScript 提供了强大的映射修饰符来改变映射类型中属性的特性。其中,? 修饰符用于将属性标记为可选(Optional)。通过在映射类型中直接应用 ?,我们可以精确控制哪些属性是可选的。

AISEO
AISEO

AI创作对SEO友好的文案和文章

AISEO 56
查看详情 AISEO

将 ? 修饰符应用于上述 MyNewDictionary 的定义,可以使其内部的键变为可选:

type MyNewDictionaryCorrected = {
  [pKey in AbcTypes]?: { // 使第一层键可选
    [eKey in DefTypes]?: { // 使第二层键可选
      onClick: () => void;
      onCancel: () => void;
    }
  }
};
登录后复制

在这个修正后的类型定义中:

  • [pKey in AbcTypes]?:表示 MyNewDictionaryCorrected 的第一层属性,其键名来自 AbcTypes,但这些属性是可选的。
  • [eKey in DefTypes]?:表示内层对象的属性,其键名来自 DefTypes,同样是可选的。

3. 完整示例与验证

现在,使用 MyNewDictionaryCorrected 类型,我们可以创建只包含部分键的对象,而不会遇到类型错误:

export const ABC = {
  A: 'A',
  B: 'B',
  C: 'C',
} as const;

export const DEF = {
  D: 'D',
  E: 'E',
  F: 'F',
} as const;

export type AbcTypes = (typeof ABC)[keyof typeof ABC];
export type DefTypes = (typeof DEF)[keyof typeof DEF];

type MyNewDictionaryCorrected = {
  [pKey in AbcTypes]?: {
    [eKey in DefTypes]?: {
      onClick: () => void;
      onCancel: () => void;
    }
  }
};

// 示例 1:只包含一个顶层键和一个内层键
const dictionary1: MyNewDictionaryCorrected = {
  [ABC.A]: {
    [DEF.D]: {
      onClick: () => console.log('A.D onClick'),
      onCancel: () => console.log('A.D onCancel'),
    }
  }
};
console.log(dictionary1); // 类型检查通过

// 示例 2:包含多个顶层键,但每个顶层键下只包含部分内层键
const dictionary2: MyNewDictionaryCorrected = {
  [ABC.A]: {
    [DEF.D]: { onClick: () => {}, onCancel: () => {} },
    [DEF.F]: { onClick: () => {}, onCancel: () => {} },
  },
  [ABC.C]: {
    [DEF.E]: { onClick: () => {}, onCancel: () => {} },
  }
};
console.log(dictionary2); // 类型检查通过

// 示例 3:尝试使用非定义的键,会报错
// const invalidDictionary: MyNewDictionaryCorrected = {
//   'X': { // 错误:类型 '"X"' 不可分配给类型 'AbcTypes'
//     [DEF.D]: { onClick: () => {}, onCancel: () => {} }
//   }
// };
登录后复制

通过这个例子,我们可以看到 MyNewDictionaryCorrected 成功地实现了我们的需求:键名受限于 AbcTypes 和 DefTypes,但它们都是可选的。

4. 总结与注意事项

  • 映射修饰符的力量:? 是 TypeScript 映射类型中非常有用的修饰符,它允许我们精确地控制属性的可选性。除了 ?,还有 readonly 修饰符(以及它们的逆操作 -? 和 -readonly),用于控制属性的只读性。
  • Partial<T> 与映射修饰符:虽然 Partial<T> 可以使一个类型的所有顶层属性变为可选,但对于嵌套的映射类型,直接在映射类型定义中应用 ? 提供了更细粒度的控制,尤其是在我们希望某些层级保持可选,而其他层级仍是强制时。在本文的场景中,由于是嵌套的映射类型,直接在每个映射表达式后添加 ? 是最直接有效的方案。
  • 类型安全与灵活性:这种方式在保证类型安全的同时,极大地提升了对象定义的灵活性。我们既能限制允许的键集,又能避免强制所有键都必须存在的冗余。

掌握映射类型及其修饰符是 TypeScript 高级用法中的重要一环,它能帮助我们构建出更健壮、更灵活且易于维护的代码。

以上就是TypeScript 教程:在映射类型中实现可选且受限的对象键的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号