TypeScript能否基于ICVSection数组构造目标Schema类型?
基于数组构造对应键值对类型的TypeScript实现方案
当然可以实现!TypeScript的类型系统提供了足够的能力,让你从现有的数组值中推导出目标的Schema类型,下面是具体的实现步骤和原理:
关键前提:保留数组元素的字面量类型
首先要注意,默认情况下TypeScript会把数组的类型拓宽为ICVSection[],这会导致namespace的类型变成宽泛的string,而不是具体的'common'、'summary'这些字面量值。所以我们需要用as const断言来强制TypeScript保留每个元素的精确类型:
import * as Yup from 'yup'; // 假设已定义的Yup Schema示例 const CommonValidationSchema = Yup.object({ name: Yup.string().required() }); const SummarySchema = Yup.object({ bio: Yup.string().max(500) }); // 用as const断言保留字面量类型 const CVSections = [ { namespace: 'common', validation: CommonValidationSchema }, { namespace: 'summary', validation: SummarySchema } // 后续新增的section也会自动被类型识别 ] as const;
构造目标Schema类型
接下来我们可以用TypeScript的映射类型(结合联合类型提取)来生成Schema类型。有两种写法,推荐第二种更简洁的方式(需要TypeScript 4.1+支持,现在大部分项目都满足这个版本要求):
写法一:使用Extract提取对应元素类型
type Schema = { // 遍历所有namespace字面量作为键 [K in typeof CVSections[number]['namespace']]: // 从数组元素联合类型中提取namespace等于K的元素,取其validation类型 Extract<typeof CVSections[number], { namespace: K }>['validation'] };
写法二:使用映射类型的as子句(更简洁)
type Schema = { // 直接将每个数组元素的namespace作为键,validation作为值类型 [Item in typeof CVSections[number] as Item['namespace']]: Item['validation'] };
验证结果
此时Schema类型会被TypeScript自动推导为:
type Schema = { common: typeof CommonValidationSchema; summary: typeof SummarySchema; // 数组中新增的section会自动同步到这个类型中 };
额外说明
- 如果
ICVSection接口只是用来约束数组元素,其实可以省略,让TypeScript自动推导数组元素的类型,这样代码更简洁。 - 只要你后续在
CVSections数组中新增符合结构的元素,Schema类型会自动更新对应的键值对,不需要手动修改类型定义。
内容的提问来源于stack exchange,提问作者gmlt.A
相关产品推荐
相关产品推荐

