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

如何用TypeScript约束字符串为合法邮箱格式?

实现编译时+运行时双重验证的邮箱字符串类型

要实现既能约束邮箱格式、又能直接当作原始字符串使用的类型,可以结合TypeScript的品牌类型(Branded Types)和模板字面量类型,配合验证函数来完成。

1. 定义带格式约束的品牌类型

首先定义Email类型,用模板字面量做基础格式检查,同时添加品牌标记让TypeScript识别这是经过验证的邮箱:

// 基础格式约束:必须包含@和.,且前后有内容
type Email = `${string}@${string}.${string}` & { __brand: 'Email' };

这里的__brand是类型层面的标记,运行时不会存在,所以Email本质还是字符串类型,能直接使用所有字符串方法。

2. 编写运行时验证函数

用正则实现严谨的邮箱格式验证,同时用类型谓词让TypeScript识别验证通过的字符串为Email类型:

// 运行时邮箱验证正则(覆盖大部分合法邮箱格式)
function isValidEmail(str: string): str is Email {
  const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
  return emailRegex.test(str);
}

3. 工厂函数创建验证后的邮箱

通过工厂函数统一处理邮箱创建,确保只有验证通过的字符串才能被赋值给Email类型变量:

function createEmail(str: string): Email {
  if (!isValidEmail(str)) {
    throw new Error('无效的邮箱格式');
  }
  // 断言为Email类型,让TypeScript认可这是合法邮箱
  return str as Email;
}

4. 使用示例

let email: Email;

// 直接赋值无效字面量 → 编译报错
email = "myEmail"; // ❌ 编译错误:类型 '"myEmail"' 无法赋值给类型 'Email'

// 直接赋值有效字面量 → 编译通过
email = "myEmail@stackoverflow.com"; // ✅ 编译通过

// 处理动态输入(比如用户输入)
const userInput = "invalid-email";
// email = userInput; // ❌ 编译错误:类型 'string' 无法赋值给类型 'Email'
try {
  email = createEmail(userInput); // ❌ 运行时抛出错误:无效的邮箱格式
} catch (e) {
  console.log((e as Error).message);
}

// 验证通过的邮箱可直接当作字符串使用
email = createEmail("myEmail@stackoverflow.com");
console.log(email); // 输出:myEmail@stackoverflow.com
console.log(email.includes("@")); // 输出:true
console.log(email === "myEmail@stackoverflow.com"); // 输出:true

说明

  • 编译时:模板字面量会检查字面量的基础格式,动态字符串必须通过createEmail才能赋值给Email类型,否则TypeScript直接报错。
  • 运行时:createEmail里的正则验证会拦截所有无效格式的邮箱,确保运行时不会出现非法值。
  • 易用性:Email类型本质还是字符串,不需要像包装类那样通过value属性访问,直接调用字符串方法、打印、比较都和普通字符串完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 17:35:39