ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

type-challenges 第 11 题解析:Tuple to Object 元组到对象类型转换

type-challenges 第 11 题解析:Tuple to Object 元组到对象类型转换 示例工程【免费下载链接】type-challengesCollection of TypeScript type challenges with online judge项目地址https://gitcode.com/GitHub_Trending/ty/type-challenges点击查看免费下载本篇文章围绕 type-challengesTypeScript 类型挑战在线题库中的第 11 题Tuple to Object展开讲解如何把只读元组as const数组的每个元素值转换为对象类型的 key 与 value并延伸到readonly any[]约束、Symbol 与混合元组等边界情况同时结合仓库源码与关联题目Tuple to Union、Tuple to Enum Object、Tuple to Nested Object、Union to Tuple构建完整学习链路。读完本文你将掌握映射类型Mapped Type在元组场景下的核心用法并理解为什么必须用T[number]提取元组元素联合类型。题目背景与目标Tuple to Object是 type-challenges 的 Easy 难度题目编号 11由作者 sinoon。题目的英文原文要求是Given an array, transform it into an object type and the key/value must be in the provided array.给定一个数组将其转换为对象类型且 key/value 必须来自该数组。韩文版本README.ko.md描述为배열(튜플)을 받아, 각 원소의 값을 key/value로 갖는 오브젝트 타입을 반환하는 타입을 구현하세요.接收一个数组/元组实现一个返回以每个元素的值作为 key/value 的对象类型的类型。题目给出的示例const tuple [tesla, model 3, model X, model Y] as const type result TupleToObjecttypeof tuple // expected { tesla: tesla, model 3: model 3, model X: model X, model Y: model Y}也就是说对于字符串字面量元组[tesla, model 3, model X, model Y]我们要把它转换成一个对象类型其中每个 key 及其对应 value 都是元组中的元素值本身。模板与测试用例理解题目的验收标准初始模板本题目录中的 template.ts 给出了初始模板我们只需补全any部分type TupleToObjectT extends readonly any[] any注意模板已经提供了约束T extends readonly any[]这意味着输入类型必须是一个只读数组/元组。之所以是readonly是因为题目示例使用了as constas const产生的元组是readonly的。测试用例揭示的完整验收标准test-cases.ts 中给出了完整的验收用例它们比 README 示例更全面地覆盖了各种边界情况import type { Equal, Expect } from type-challenges/utils const tuple [tesla, model 3, model X, model Y] as const const tupleNumber [1, 2, 3, 4] as const const sym1 Symbol(1) const sym2 Symbol(2) const tupleSymbol [sym1, sym2] as const const tupleMix [1, 2, 3, 4, sym1] as const type cases [ ExpectEqualTupleToObjecttypeof tuple, { tesla: tesla, model 3: model 3, model X: model X, model Y: model Y }, ExpectEqualTupleToObjecttypeof tupleNumber, { 1: 1, 2: 2, 3: 3, 4: 4 }, ExpectEqualTupleToObjecttypeof tupleSymbol, { [sym1]: typeof sym1, [sym2]: typeof sym2 }, ExpectEqualTupleToObjecttypeof tupleMix, { 1: 1, 2: 2, 3: 3, 4: 4, [sym1]: typeof sym1 }, ] // ts-expect-error type error TupleToObject[[1, 2], {}]从中可以提炼出四个关键验收点字符串字面量元组[tesla, ...]→ 每个字符串既是 key 也是 value。数字字面量元组[1, 2, 3, 4]→ 结果{ 1: 1, 2: 2, 3: 3, 4: 4 }数字字面量类型可以直接作为对象 key。Symbol 元组[sym1, sym2]→ 结果{ [sym1]: typeof sym1, [sym2]: typeof sym2 }说明 key 可以是symbol类型且需要保留typeof sym1这样的唯一 symbol 类型。混合元组[1, 2, 3, 4, sym1]→ 数字、字符串、symbol 混合作 key全部保留字面量类型。错误用例TupleToObject[[1, 2], {}]必须报错ts-expect-error因为当元组元素是数组或对象时它们不能被用作对象 key。其中Equal与Expect来自仓库的 utils/index.d.tsEqual通过(T() T extends X ? 1 : 2) extends (T() T extends Y ? 1 : 2)的双函数签名比对实现严格的类型等价判断ExpectT extends true T则要求传入的类型必须为true否则编译失败。解法一借助T[number]提取元素联合类型核心实现最简洁、也是最符合题目意图的解法是利用索引访问类型Indexed Access Types中的T[number]type TupleToObjectT extends readonly any[] { [K in T[number]]: K }原理拆解T[number]会取出元组中所有元素类型的联合。例如对[tesla, model 3, model X, model Y]T[number]得到tesla | model 3 | model X | model Y。[K in T[number]]是映射类型Mapped Type对联合类型中的每个成员K生成一个属性。: K表示该属性的值类型就是 key 本身。因此TupleToObjecttypeof tuple展开为{ tesla: tesla model 3: model 3 model X: model X model Y: model Y }数字元组[1, 2, 3, 4]的T[number]是1 | 2 | 3 | 4映射后得到{ 1: 1, 2: 2, 3: 3, 4: 4 }混合元组的T[number]是1 | 2 | 3 | 4 | typeof sym1映射后得到{ 1: 1, 2: 2, 3: 3, 4: 4, [sym1]: typeof sym1 }与测试用例完全吻合。为什么不能用keyof T或keyof typeof tuple初学者容易误写成[K in keyof T]: K或[K in keyof T]: T[K]。但keyof T返回的是数组的索引/方法如number、length、push等而不是元素值。例如keyof [a,b]会包含0 | 1 | length | push | ...这显然不是题目期望的结果。T[number]才是专门用于提取数组元素类型的索引访问方式。为什么错误用例会报错对于TupleToObject[[1, 2], {}]T[number]得到[1, 2] | {}。映射类型要求 key 必须是string | number | symbol类型而数组类型[1, 2]和对象类型{}都不满足因此 TypeScript 编译器会报错 Type [1, 2] | {} is not assignable to type string | number | symbol。这正是测试用例中用ts-expect-error断言的原因——我们的实现必须让非法输入在编译期被拒绝。解法二利用 in 操作符约束元素类型另一种常见解法是在 key 类型上增加类型守卫将元素类型限定为string | number | symboltype TupleToObjectT extends readonly any[] { [K in T[number] as K extends string | number | symbol ? K : never]: K }这里使用了key remappingkey 重映射语法as如果元素K是合法的对象 key 类型string | number | symbol则保留为 key否则映射为never即被剔除。该写法在语义上显式表达只有可作为对象 key 的元素才能进入结果与题目约束key/value 必须来自给定数组的精神一致也更容易向读者解释为什么数组、对象元素会被拒绝。验证方式在仓库中跑通测试本仓库采用 pnpm workspace 管理见 package.json 与 pnpm-workspace.yaml测试工具type-challenges/utils通过workspace:*引用。你可以把上述任一实现填入 template.ts然后通过 TypeScript 编译器对 test-cases.ts 进行类型检查# 安装依赖在仓库根目录 pnpm install # 对指定题目的测试用例做类型检查 pnpm exec tsc --noEmit questions/00011-easy-tuple-to-object/test-cases.ts如果实现正确类型检查将通过所有ExpectEqual...都被满足如果实现错误例如误用keyof T编译会直接报错。这也是 type-challenges 在线判题系统tsch.js.org在本地验证的标准思路。同主题延伸从 Tuple to Object 出发的进阶路线本题目录的 info.yml 声明了相关题目related: 10, 472, 730, 3188官方也把这四个题目作为关联挑战构成一条由易到难的完整学习路径10 · Tuple to UnionMedium——把元组转成联合类型questions/00010-medium-tuple-to-union/README.md 要求实现TupleToUnionT把元组的值转换为联合类型。示例TupleToUnion[1, 2, 3]结果为1 | 2 | 3。它的核心就是T[number]——理解了 Tuple to Object 中提取元素联合类型的手法这道 Medium 题只需type TupleToUnionT extends readonly any[] T[number]它是我们第 11 题解法的减法版本T[number]直接作为结果返回而不再做映射。472 · Tuple to Enum ObjectHard——元组转枚举风格对象questions/00472-hard-tuple-to-enum-object/README.md 要求把字符串元组转换为类似枚举的对象Enum[macOS, Windows, Linux]得到{ readonly MacOS: macOS, readonly Windows: Windows, readonly Linux: Linux }若第二个参数为true则值变为数字字面量0, 1, 2对应 TypeScript 枚举编译产物OperatingSystem[OperatingSystem[MacOS] 0] MacOS的形态。实现需结合模板字面量类型做 PascalCase 转换并处理readonly修饰符。模板见 template.tstype EnumT extends readonly string[], N extends boolean false any。3188 · Tuple to Nested ObjectMedium——元组驱动递归嵌套对象questions/03188-medium-tuple-to-nested-object/README.md 要求用元组路径递归构建嵌套对象TupleToNestedObject[a, b], number得到{ a: { b: number } }空元组则直接返回U。它把元组→对象从一层映射扩展到递归逐层解构是理解T extends [infer F, ...infer R]递归写法的绝佳练习。730 · Union to TupleHard——反向联合转元组questions/00730-hard-union-to-tuple/README.md 是反向题目要求把联合类型转回元组。注意联合是无序结构因此输出元组的任意排列都算正确同时要处理联合坍缩如any | a会坍缩为anynever | a会坍缩为a。该题通常需要借助函数逆变与infer提取难度远高于本题属于对 Tuple/Union 关系的终极考察。总结Tuple to Object 是 type-challenges Easy 难度中的经典一题它用最简短的代码浓缩了两个 TypeScript 类型系统核心知识点T[number]从元组类型提取元素联合类型的关键索引访问语法映射类型 索引签名兼容性[K in T[number]]: K让联合类型成员成为对象 key并要求元素必须是string | number | symbol。配合 test-cases.ts 的五个用例字符串/数字/Symbol/混合/非法输入我们可以完整验证实现正确性。而通过官方关联的 10、472、730、3188 四道题目你可以从元组→对象出发一路延伸到元组→联合元组→枚举对象元组→嵌套对象直至反向的联合→元组系统性掌握 TypeScript 中数组与对象类型转换的完整图景。赞分享示例工程【免费下载链接】type-challengesCollection of TypeScript type challenges with online judge项目地址https://gitcode.com/GitHub_Trending/ty/type-challenges点击查看免费下载相关推荐RunCat 365 多语言支持四步实战让任务栏小猫切换成你的语言RunCat 365 多语言支持四步实战让任务栏小猫切换成你的语言 RunCat 365 是一款跑在 Windows 任务栏上的系统监控工具一只小猫CPU示例工程掌握Type Challenges元组转对象的终极指南掌握Type Challenges元组转对象的终极指南 Type Challenges是一个专注于提升TypeScript和泛型编程能力的学习项目通过一系列示例工程Type Challenges项目元组转对象类型解析Type Challenges项目元组转对象类型解析 在TypeScript类型编程中经常需要将一种类型转换为另一种类型。Type Challenges项目示例工程上一篇KubeVela Addon 目录结构与开发指南以 FluxCD 示例 Addon 为骨架深入解析下一篇Florida高级技巧线程循环优化与内存描述符隐藏实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表