如何基于对象属性创建TypeScript类型并确保类型与属性校验?
问题描述
现有如下对象数组:
const formTest = [ { label: "test", name: "grossSalary" }, { label: "test", name: "privatePension" }, ];
希望基于数组中所有name属性构建一个类型,最终生成如下结果:
type FormValues = { grossSalary: string; privatePension: string; }
要求该类型能严格校验属性,例如以下代码因包含不存在的invalidProperty,应当触发TypeScript错误:
const initialValues: FormValues = { grossSalary: "", invalidProperty: "", }
尝试使用映射类型实现:
type FormValues = { [K in typeof formTest[number]["name"]]: string; }
但该方式仅校验属性类型,不会对额外属性报错,请问该如何解决?
解决方案
核心问题有两个:一是原数组formTest的类型被TypeScript推断为宽泛的string集合,而非具体的字符串字面量;二是TypeScript默认的结构类型兼容规则允许对象字面量存在额外属性。要实现严格校验,需按以下步骤处理:
1. 将数组转为只读字面量类型
通过as const断言,强制TypeScript把数组中name属性的值识别为具体的字符串字面量,而非通用的string类型:
const formTest = [ { label: "test", name: "grossSalary" }, { label: "test", name: "privatePension" }, ] as const;
2. 构建严格校验的类型
这里提供两种可行方案:
方案一:添加never类型索引签名禁止额外属性
给映射类型追加一个匹配所有字符串键的索引签名,将其类型设为never,这样任何不在name集合中的属性都会触发类型错误:
type FormValues = { [K in typeof formTest[number]["name"]]: string; } & { [key: string]: never; };
此时定义包含invalidProperty的initialValues,TypeScript会报错:类型“string”不能赋值给类型“never”,严格拦截额外属性。
方案二:使用satisfies运算符(TypeScript 4.9+)
若不想修改FormValues的类型结构,可在变量赋值时用satisfies运算符做严格校验:
type FormValues = { [K in typeof formTest[number]["name"]]: string; }; const initialValues = { grossSalary: "", invalidProperty: "", } satisfies FormValues; // 此处直接报错,提示额外属性不存在
这种方式更灵活,仅在赋值阶段做校验,不改变原类型的兼容性。
内容的提问来源于stack exchange,提问作者Berg_Durden
相关产品推荐
相关产品推荐

