TypeScript中如何提取数组对象属性值生成对应联合类型?
TypeScript从数组提取属性值字面量联合类型实现方案
要实现从数组中提取指定属性的字面量联合类型,核心需要两步:一是让TypeScript保留数组内属性的字面量类型,避免被拓宽为通用的string类型;二是通过索引访问类型提取对应属性的联合值。
最简实现(推荐)
给原数组添加as const常量断言,锁定数组内部所有值的字面量类型,再通过索引访问语法提取属性:// as const 禁止类型拓宽,保留每个id的字面量值 const d = [{id: 'Cat'}, {id: 'Dog'}] as const; type ids = typeof d[number]['id']; // 此时ids的类型为 'Cat' | 'Dog',完全符合要求实现原理说明:
typeof d拿到整个数组的类型[number]是数组类型的标准索引访问写法,传入number可以拿到数组所有元素组成的联合类型,即{readonly id: "Cat"} | {readonly id: "Dog"}- 最后拼接
['id'],即可取出联合类型中每个成员的id属性值,组成最终的字面量联合类型
不修改原数组声明的兼容写法(TS 5.0+支持)
如果数组是外部传入、不方便直接加as const,可以用const类型参数封装工具函数,自动保留字面量类型:// 封装通用的字面量数组固定函数 const makeLiteralArray = <const T extends readonly unknown[]>(arr: T) => arr; const d = makeLiteralArray([{id: 'Cat'}, {id: 'Dog'}]); type ids = typeof d[number]['id']; // 同样得到 'Cat' | 'Dog'生成类const枚举的使用方案
如果需要和枚举一致的使用体验,可以直接基于提取的类型生成常量对象,编译后和const枚举效果一致,不需要重复维护枚举值:const d = [{id: 'Cat'}, {id: 'Dog'}] as const; type ids = typeof d[number]['id']; // 基于数组自动生成常量映射,和const枚举使用方式完全一致 const IdEnum = Object.fromEntries(d.map(item => [item.id, item.id])) as Record<ids, ids>; // 使用:IdEnum.Cat 类型为'Cat',值为'Cat';IdEnum.Dog 类型为'Dog',值为'Dog'
注意:如果不加
as const或者const类型参数,TypeScript会默认把数组里的id类型拓宽为string,最终提取出的ids类型会是string,无法拿到精确的字面量联合。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

