You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript如何定义仅允许小写字母的字符串字面量类型

现有实现的问题
  • 递归逻辑错误:你定义的LowerString终止分支返回的是单个小写字母联合类型${Lower},无法适配不同长度的输入字符串;同时递归拼接时直接用了任意小写字母而非原字符串的字符,导致最终类型会被推导为所有可能的小写字母组合的联合,无法起到校验传入字符串是否全小写的作用。
  • 泛型使用不符合预期:你将LowerString<string>作为泛型约束传入时,TS无法对宽泛的string类型做细粒度的字面量校验,同时额外定义ID泛型参数也增加了使用成本。

另外补充说明:TypeScript目前的类型系统不支持对宽泛的string类型做默认的小写约束,必须在字面量推导的场景下才能触发校验,不需要额外加泛型的实现可以参考以下方案。

修正方案

方案1:基于自定义小写字母枚举的实现

修正后的LowerString类型可以正确校验字符串是否全为小写字母:

type Lower =
  | "a"
  | "b"
  | "c"
  | "d"
  | "e"
  | "f"
  | "g"
  | "h"
  | "i"
  | "j"
  | "k"
  | "l"
  | "m"
  | "n"
  | "o"
  | "p"
  | "q"
  | "r"
  | "s"
  | "t"
  | "u"
  | "v"
  | "w"
  | "x"
  | "y"
  | "z";

type LowerString<T extends string> = 
  T extends `${infer First}${infer Rest}` 
    ? First extends Lower 
      ? `${First}${LowerString<Rest>}`
      : never
    : T;

不需要给Resource加泛型的写法,配合TS 4.9+的satisfies操作符使用即可:

type Resource = {
  id: string;
};

// 合法示例,正常通过校验
const validResource = {
  id: "user123"
} satisfies Resource & { id: LowerString<typeof validResource.id> };

// 非法示例,包含大写字母会触发编译报错
const invalidResource = {
  id: "User123"
} satisfies Resource & { id: LowerString<typeof invalidResource.id> };

方案2:基于TS内置工具类型的简化实现

TS本身提供了内置的Lowercase工具类型,可以直接用来判断字符串是否全小写,不需要手动枚举所有小写字母:

type LowerString<T extends string> = T extends Lowercase<T> ? T : never;

// 基于标签类型实现无额外语法的校验
type LowercaseString = string & { __tag: 'lowercase' };

function defineLowerId<T extends string>(id: LowerString<T>): LowercaseString {
  return id as LowercaseString;
}

type Resource = {
  id: LowercaseString;
};

// 合法示例
const res: Resource = {
  id: defineLowerId("order2024")
};

// 非法示例,包含大写字母编译报错
const invalidRes: Resource = {
  id: defineLowerId("Order2024")
};

内容的提问来源于stack exchange,提问作者user3612643

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 22:24:03