TypeScript能否为原始类型定义自定义类型规则?如何实现AllCapsString?
如何在TypeScript中定义自定义原始类型规则(比如AllCapsString)
当然可以实现!在TypeScript里,我们可以通过**品牌类型(Branded Types)**结合类型守卫或断言函数,来给原始类型定义自定义的校验规则,你想要的AllCapsString完全能做到。下面分两种常用场景给你详细说明:
一、通用方案:支持动态字符串(兼顾编译+运行时校验)
这个方案适合需要处理动态生成字符串的场景,既能在编译时做类型约束,也能在运行时做校验。
1. 定义品牌化的AllCapsString类型
我们给普通string加上一个独特的“品牌”标记,让TypeScript把它和普通字符串区分开:
// 品牌类型:给string添加唯一标识,避免和普通string混淆 type AllCapsString = string & { __brand: 'AllCapsString' };
2. 编写校验函数(断言函数/类型守卫)
接下来写一个函数来验证字符串是否符合全大写要求,并帮TypeScript做类型窄化:
方式A:断言函数(直接抛出错误)
function assertAllCaps(str: string): asserts str is AllCapsString { if (str !== str.toUpperCase()) { throw new Error(`Invalid AllCapsString: "${str}" 不是全大写格式!`); } }
使用示例:
// 错误示例:运行时会抛出错误 const invalidStr = "this is a string"; assertAllCaps(invalidStr); // 这里直接报错 let test1: AllCapsString = invalidStr; // 编译时通过,但运行时失败 // 正确示例:编译+运行都通过 const validStr = "THIS IS A STRING"; assertAllCaps(validStr); let test2: AllCapsString = validStr; // 类型检查通过
方式B:类型守卫函数(返回布尔值)
如果你不想直接抛出错误,也可以用类型守卫做条件判断:
function isAllCaps(str: string): str is AllCapsString { return str === str.toUpperCase(); }
使用示例:
const maybeCaps = "HELLO WORLD"; if (isAllCaps(maybeCaps)) { let test3: AllCapsString = maybeCaps; // 进入分支后,类型自动窄化为AllCapsString }
二、字面量专属方案:仅编译时校验
如果你的场景只需要针对字面量字符串做编译时校验,不需要处理动态字符串,可以用模板字面量类型实现:
// 仅接受全大写的字面量字符串 type AllCapsString<T extends string> = T extends Uppercase<T> ? T : never;
使用示例:
// 编译通过:字面量是全大写 let test4: AllCapsString<"THIS IS GOOD"> = "THIS IS GOOD"; // 编译错误:字面量不是全大写 let test5: AllCapsString<"this is bad"> = "this is bad";
这个方案的局限性是只能处理硬编码的字面量字符串,无法对变量赋值的动态字符串做校验。
总结
- 针对原始类型的自定义规则,TypeScript通过品牌类型+校验函数的组合,能完美实现编译时约束+运行时校验的需求;
- 字面量模板方案则更轻量,适合只需要编译时校验的场景。
内容的提问来源于stack exchange,提问作者Jonny Asmar
相关产品推荐
相关产品推荐

