如何在TypeScript类型中将PascalCase转换为strictCamelCase
实现支持大写缩写的StrictCamelCase转换类型
TypeScript内置的Uncapitalize<S>可以轻松将FooBar这类普通PascalCase字符串转为fooBar:
const fooBar: Uncapitalize<'FooBar'> = 'fooBar';
但面对HTML5规范里带连续大写缩写的类名(比如XMLHttpRequest)时,这个方法就失效了——它只会把第一个大写字母转小写,导致结果变成不符合预期的xMLHttpRequest。
我们需要实现一个自定义类型,满足两个核心要求:
- 将包含连续大写字母缩写的PascalCase类型,转换为缩写全小写的strictCamelCase类型;
- 转换后不存在连续大写字母的情况。
实现方案
利用TypeScript模板字面量的类型推断特性,通过递归逐个处理连续大写字母,避免贪婪匹配问题:
type StrictUncapitalize<S extends string> = S extends `${infer C}${infer D}${infer Rest}` ? C extends Uppercase<C> ? D extends Uppercase<D> // 连续大写:转小写当前字符后递归处理剩余部分 : `${Lowercase<C>}${StrictUncapitalize<`${D}${Rest}`>}` // 大写+非大写:仅转当前字符,后续保持原样 : `${Lowercase<C>}${D}${Rest}` : `${C}${D}${Rest}` // 单个字符直接转小写 : S extends `${infer C}` ? Lowercase<C> : S;
测试验证
用示例场景测试这个类型:
// 预期:"xmlHttpRequest" type XMLTest = StrictUncapitalize<'XMLHttpRequest'>; // 预期:"htmlAnchorElement" type HTMLTest = StrictUncapitalize<'HTMLAnchorElement'>; // 预期:"foobaaAr" type MixedTest = StrictUncapitalize<'FOOBaAAr'>; // 普通PascalCase也能正常处理:"fooBar" type NormalTest = StrictUncapitalize<'FooBar'>;
工作原理
这个类型通过分层判断处理字符串:
- 先尝试将字符串拆分为「首字符C + 次字符D + 剩余部分Rest」;
- 如果C是大写字符,再检查D是否也是大写:
- 若D为大写,说明仍处于连续缩写段,将C转小写后递归处理
${D}${Rest},直到遇到非大写字符; - 若D为非大写,说明缩写段结束,仅将C转小写,后续字符保持原结构;
- 若D为大写,说明仍处于连续缩写段,将C转小写后递归处理
- 对于单个字符的情况,直接转为小写;
- 非大写开头的字符串直接返回(兼容非标准输入,核心仍针对PascalCase场景)。
内容的提问来源于stack exchange,提问作者jason.
相关产品推荐
相关产品推荐

