如何在TypeScript中实现对象属性与排序数组的动态匹配校验?
问题
我有一个包含指定属性(props)的对象,以及一个描述这些属性在网格中排列方式的数组(order)。order数组中的每个元素代表网格的一行:若元素是单个属性名,则该属性占据整行;若元素是属性名元组,则这些属性并排显示。
示例用法:
const a: OrderedProperties = { props: ['title', 'firstName', 'lastName', 'nickName'], order: [ 'title', ['firstName', 'lastName'], 'nickName' ] }
但当前的OrderedProperties类型并未校验order数组中的值是否与props数组中的属性名匹配:
export type OrderGrid = Array<string | [string, string]>; export type OrderedProperties = { props: string[]; order: OrderGrid };
如何让TypeScript动态校验order字段中的字符串是否匹配props数组中的属性名?
解决方案
要实现order与props的动态校验,核心是利用TypeScript的泛型和字面量类型推断,让TypeScript根据props的具体值约束order的取值范围。
1. 定义泛型约束类型
先把OrderGrid和OrderedProperties改为泛型类型,接收属性名的联合类型作为参数:
// 定义单行的类型:要么是单个属性名,要么是两个属性名的元组 type OrderRow<T extends string> = T | [T, T]; // 定义整个网格的类型:多行的数组 type OrderGrid<T extends string> = OrderRow<T>[]; // 泛型的OrderedProperties,props的元素类型和order的元素类型统一为T type OrderedProperties<T extends string> = { props: T[]; order: OrderGrid<T>; };
2. 直接使用泛型创建对象
手动指定泛型的联合类型,TypeScript会自动校验order中的值是否都在props的属性列表里:
// 合法示例:所有order值都匹配props,无报错 const validConfig: OrderedProperties<'title' | 'firstName' | 'lastName' | 'nickName'> = { props: ['title', 'firstName', 'lastName', 'nickName'], order: [ 'title', ['firstName', 'lastName'], 'nickName' ] }; // 非法示例:order中出现props没有的'age',TypeScript直接报错 const invalidConfig: OrderedProperties<'title' | 'firstName'> = { props: ['title', 'firstName'], order: [ 'title', ['firstName', 'age'] // 类型错误:'age'不在允许的属性集合中 ] };
3. 简化类型推断(推荐)
如果不想手动写联合类型,可以封装一个工具函数,让TypeScript自动推断props的字面量类型:
function createOrderedGrid<T extends string>(props: T[], order: OrderGrid<T>) { return { props, order }; } // 自动推断props的类型,order会被自动约束 const autoInferredConfig = createOrderedGrid( ['title', 'firstName', 'lastName', 'nickName'], [ 'title', ['firstName', 'lastName'], 'nickName' ] ); // 非法示例:order中出现不存在的属性,立即触发类型错误 const badConfig = createOrderedGrid( ['title', 'firstName'], [ 'title', ['firstName', 'age'] // 类型错误 ] );
优势说明
- 完全在编译期完成校验,不影响运行时性能
- 只要order中出现props以外的属性,TypeScript会实时抛出错误
- 完美支持单行单个属性、双属性并排的两种布局格式约束
内容的提问来源于stack exchange,提问作者GoncaloNGT
相关产品推荐
相关产品推荐

