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

TypeScript 如何实现匹配含非负整数且后可跟空格的字符串类型

问题分析

你的实现无法匹配末尾带空格的字符串,核心是两个问题:

  1. TypeScript的模板字面量infer拆分逻辑不支持基于自定义递归类型的自动拆分:你在Input类型中写的${Integer<infer I>}${Whitespaces<infer W>}属于自定义约束模式,TS类型系统不会主动对输入字符串做回溯拆分来分别满足Integer和Whitespaces的约束,因此无法将"123 "自动拆分为I="123"、W=" "的结构。
  2. 递归终止分支存在隐患:你的Digits类型在遇到非数字字符时会返回空字符串,会导致存在非数字字符的字符串错误通过前置数字部分的校验,比如"12a3"会被Digits计算为"12",出现误判。
修复方案

调整类型逻辑,先拆分字符串的全部前缀和后缀,再分别校验前缀为合法非负整数、后缀全为空格即可,既避免联合类型爆炸,也符合TS的类型推导规则:

type NonZeroDigit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
type Digit = "0" | NonZeroDigit;

// 校验是否为合法非负整数字符串:不能是0开头的多位数,只能由数字组成
type ValidInt<T extends string> = 
  T extends '0' 
    ? T
    : T extends `${NonZeroDigit}${infer Rest}`
      ? Rest extends ''
        ? T
        : Rest extends `${Digit}${infer _}`
          ? ValidInt<Rest>
          : never
      : never;

// 校验是否为全空格字符串(支持空字符串)
type AllSpaces<T extends string> = 
  T extends ''
    ? T
    : T extends ` ${infer Rest}`
      ? AllSpaces<Rest>
      : never;

// 整体校验:拆分整数部分和剩余部分分别校验
type Input<T extends string> = 
  T extends `${infer IntPart}${infer Rest}`
    ? IntPart extends ValidInt<IntPart>
      ? Rest extends AllSpaces<Rest>
        ? T
        : never
      : never
    : never;

function test<T extends string>(foo: Input<T>) {}
校验效果
test("0");        // OK
test("1234");     // OK
test("42 ");      // OK
test("100     "); // OK

test("-9");   // 类型错误
test("");     // 类型错误
test(" ");    // 类型错误
test("0123"); // 类型错误
test("who");  // 类型错误
test("123 "); // OK

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:36:08