如何约束使用声明合并的TypeScript接口的属性命名规则?
实现带命名约束的TypeScript声明合并接口
要实现既支持多文件声明合并,又约束属性名必须遵循select${Capitalize<string>}模式的Selectors接口,可以通过TypeScript的模板字符串类型、条件类型结合全局声明来实现,具体步骤如下:
1. 定义键名约束类型
首先用模板字符串类型定义合法的键名模式:
// 匹配所有以select开头、后续首字母大写的键名,比如selectFoo、selectBar type SelectorKey = `select${Capitalize<string>}`;
2. 编写验证逻辑
通过条件类型检查接口的键是否符合约束,若存在非法键则触发编译错误:
// 提取所有不符合SelectorKey的键 type InvalidSelectorKeys<T> = Exclude<keyof T, SelectorKey>; // 验证逻辑:若存在非法键,给该键赋值带错误提示的类型,触发编译报错 type EnsureValidSelectors<T> = InvalidSelectorKeys<T> extends never ? T : { [K in InvalidSelectorKeys<T>]: `属性名 "${K}" 不符合规范,必须以"select"开头且后续首字母大写(示例:selectFoo)`; };
3. 全局声明并启用验证
在全局作用域声明Selectors接口,并添加强制验证的类型:
declare global { // 基础接口,留空供多文件合并扩展 interface Selectors {} // 强制验证Selectors的所有键是否合法,编译时自动检查 type _ValidateSelectors = EnsureValidSelectors<Selectors>; }
4. 扩展接口的示例
在任意文件中扩展Selectors接口:
declare global { interface Selectors { selectFoo: number; // 合法,无编译错误 selectBar: string; // 合法,无编译错误 // bar: boolean; // 非法,会触发报错:类型“boolean”不能赋值给类型“"属性名 \"bar\" 不符合规范,必须以"select"开头且后续首字母大写(示例:selectFoo)"” } }
核心原理说明
- 模板字符串类型
SelectorKey精准匹配合法键名的格式,确保只有selectXXX(XXX首字母大写)的键被允许。 EnsureValidSelectors类型会遍历Selectors的所有键,若存在非法键则替换为带错误提示的字符串类型,触发TypeScript的编译错误,直接提示用户修正。- 全局声明的
_ValidateSelectors会强制TypeScript在编译时对当前Selectors接口的所有键进行验证,完美兼容声明合并特性。
内容的提问来源于stack exchange,提问作者Dellirium
相关产品推荐
相关产品推荐

