如何用TypeScript泛型Record验证含指定键与validations数组的对象?
解决TypeScript中ValidatorSchema泛型的类型匹配问题
需求
需要定义TypeScript类型ValidatorSchema<T>,让对应对象满足两个条件:
- 所有键必须来自泛型参数
T(如SingleShopColumns或MultishopColumns这类字符串字面量联合类型) - 每个键对应的属性必须是包含
validations字符串数组的对象
现有问题
尝试用Record定义泛型时出现类型错误:
Type '{ SKU: { validations: string[]; }; ... }' is not assignable to type 'ValidatorSchema
'. Object literal may only specify known properties, and ''SKU'' does not exist in type 'ValidatorSchema '.
现有代码:
export type SingleShopColumns = | 'SKU' | 'Priority'; export type MultishopColumns = | 'Redundant Date' | 'Priority'; export type ValidatorSchema<T> = Record<keyof T, { validations: string[] }>; export const SINGLE_SHOP_SCHEMA: ValidatorSchema<SingleShopColumns> = { 'SKU': { validations: ['validateString'] }, 'Priority': { validations: ['validateString'] }, 'Does_not_exist_should be error': { validations: ['validateString'] } }; export const MULTISHOP_SCHEMA: ValidatorSchema<MultishopColumns> = { 'Redundant Date': { validations: ['validateString'] }, 'Priority': { validations: ['validateString'] }, };
错误原因
SingleShopColumns是字符串字面量联合类型,而非对象类型,因此keyof SingleShopColumns会返回never(字符串字面量没有自身的键)。这导致Record<keyof T, ...>等价于Record<never, ...>,也就是空对象类型,自然无法匹配包含SKU等键的对象。
正确实现方案
直接将泛型T作为Record的键类型即可(无需使用keyof),因为T本身就是合法的键类型:
export type SingleShopColumns = 'SKU' | 'Priority'; export type MultishopColumns = 'Redundant Date' | 'Priority'; // 直接用T作为Record的键类型,限定所有键必须来自T export type ValidatorSchema<T extends string> = Record<T, { validations: string[] }>; // 合法:所有键都来自SingleShopColumns,额外键会触发类型错误 export const SINGLE_SHOP_SCHEMA: ValidatorSchema<SingleShopColumns> = { 'SKU': { validations: ['validateString'] }, 'Priority': { validations: ['validateString'] }, // 'Does_not_exist_should be error': { validations: ['validateString'] } // 取消注释会触发预期错误 }; // 合法:所有键都来自MultishopColumns export const MULTISHOP_SCHEMA: ValidatorSchema<MultishopColumns> = { 'Redundant Date': { validations: ['validateString'] }, 'Priority': { validations: ['validateString'] }, };
额外优化:支持可选键
如果希望Schema可以只包含T中的部分键(而非必须全量定义),可以结合Partial实现:
export type ValidatorSchema<T extends string> = Partial<Record<T, { validations: string[] }>>; // 合法:仅定义部分允许的键 export const PARTIAL_SCHEMA: ValidatorSchema<SingleShopColumns> = { 'SKU': { validations: ['validateString'] } };
内容的提问来源于stack exchange,提问作者André Ricardo
相关产品推荐
相关产品推荐

