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

如何在TypeScript中实现仅编译时的自定义类型校验?

TypeScript编译阶段校验常量值的可行方案

完全可以在TypeScript中实现仅编译阶段的常量值校验,核心是利用TypeScript的条件类型、模板字面量类型和字面量类型约束,在编译时锁定变量的具体值并校验规则,不会产生任何运行时代码。以下是具体实现方案:

一、数值范围校验(例如:数值不得小于5)

通过条件类型判断数值是否符合范围,不符合时返回自定义错误字面量类型,编译时直接抛出对应错误:

// 定义校验类型:数值>=5则返回自身,否则返回错误信息
type Min5<N extends number> = N >= 5 ? N : `错误:数值 ${N} 必须大于等于5`;

// 合法常量:编译通过
const validNum: Min5<5> = 5;
const validNum2: Min5<12> = 12;

// 非法常量:编译报错,提示类型不匹配
const invalidNum: Min5<3> = 3;
// 报错信息:Type '3' is not assignable to type '错误:数值 3 必须大于等于5'.

二、字符串格式校验(例如:邮箱格式)

利用模板字面量类型定义合法格式,结合条件类型做校验,不符合时返回自定义错误:

// 定义基础邮箱格式的模板字面量类型
type EmailPattern = `${string}@${string}.${string}`;

// 自定义校验类型:符合邮箱格式则返回自身,否则返回错误信息
type ValidateEmail<S extends string> = S extends EmailPattern ? S : `错误:字符串 "${S}" 不符合邮箱格式`;

// 合法常量:编译通过
const validEmail: ValidateEmail<'user@example.com'> = 'user@example.com';

// 非法常量:编译报错
const invalidEmail: ValidateEmail<'userexample.com'> = 'userexample.com';
// 报错信息:Type '"userexample.com"' is not assignable to type '错误:字符串 "userexample.com" 不符合邮箱格式'.

三、复杂格式校验(例如:国内手机号)

通过infer关键字和嵌套条件类型实现多规则校验,支持更精细的格式判断:

// 校验国内11位手机号:以1开头,第二位为3/4/5/7/8,全为数字
type ValidatePhone<S extends string> = S extends `${infer D1}${infer D2}${infer Rest}`
  ? Rest extends `${string}${string}${string}${string}${string}${string}${string}${string}${string}`
    ? D1 extends '1'
      ? D2 extends '3' | '4' | '5' | '7' | '8'
        ? S extends `${number}`
          ? S
          : `错误:手机号 "${S}" 必须全为数字`
        : `错误:手机号 "${S}" 第二位必须是3/4/5/7/8`
      : `错误:手机号 "${S}" 必须以1开头`
    : `错误:手机号 "${S}" 长度必须为11位`
  : `错误:手机号 "${S}" 长度必须为11位`;

// 合法常量:编译通过
const validPhone: ValidatePhone<'13912345678'> = '13912345678';

// 非法常量:编译报错
const invalidPhone1: ValidatePhone<'1234567890'> = '1234567890'; // 长度不足
const invalidPhone2: ValidatePhone<'23912345678'> = '23912345678'; // 开头非1

核心原理说明

  • 通过指定字面量类型参数,让TypeScript将变量锁定为具体的字面量值,而非宽泛的number/string类型
  • 利用条件类型的分支判断,在编译阶段验证值是否符合规则,不符合时返回包含自定义错误信息的字面量类型,触发编译报错
  • 所有校验逻辑仅存在于编译阶段,最终生成的JavaScript代码中不会保留任何校验相关代码,完全满足“仅编译阶段校验”的需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 01:50:36