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

如何不使用类阻止TypeScript中type alias类型的实例被私自创建?

不使用类阻止类型别名实例被伪造的实现方案

TypeScript默认采用结构化类型系统,只要两个类型的结构完全匹配就会被判定为兼容,因此普通的type alias无法直接阻止结构一致的手动构造对象。你可以通过**不透明类型(Opaque Type)**方案实现需求,完全不需要依赖类:


方案1:私有Symbol标记法(最常用,编译+运行时双防护)

核心逻辑是在类型中加入一个外部无法访问的唯一Symbol标记,只有校验函数能生成带该标记的合法实例:

// 该Symbol仅当前模块可访问,不对外导出
const __ValidatedEmail = Symbol('ValidatedEmail');

// 类型定义中加入私有Symbol属性
export type ValidatedEmail = {
  address: string;
  validatedOn: Date;
  [__ValidatedEmail]: true;
}

// 仅该函数可返回合法的ValidatedEmail实例
export const validateEmail = (input: string): ValidatedEmail | Error => {
  // 你的自定义邮箱校验逻辑
  const emailReg = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
  if (!emailReg.test(input)) {
    return new Error('邮箱格式非法');
  }
  return {
    address: input,
    validatedOn: new Date(),
    [__ValidatedEmail]: true
  };
};

export const sendEmail = (email: ValidatedEmail) => {
  // 可选:运行时二次校验,拦截强行用as any绕过TS类型检查的伪造实例
  if (!(__ValidatedEmail in email)) {
    throw new Error('非法的ValidatedEmail实例,未经过校验');
  }
  // 后续发送邮件逻辑
};

外部用户因为拿不到私有__ValidatedEmail Symbol,根本无法构造符合类型要求的对象,手动写的伪造实例会直接触发TS类型报错,无法传入sendEmail。


方案2:通用Branding包装(适合批量创建多种校验类型)

如果需要做多个类似的校验类型(比如校验手机号、身份证号),可以用通用的类型标记工具复用逻辑:

// 内部私有标记,不对外导出
declare const __brand: unique symbol;
type Brand<T, Tag extends string> = T & { [__brand]: Tag };

// 定义带唯一标记的邮箱类型
export type ValidatedEmail = Brand<{
  address: string;
  validatedOn: Date;
}, 'ValidatedEmail'>;
// 可快速扩展其他校验类型
export type ValidatedPhone = Brand<{ number: string }, 'ValidatedPhone'>;

// 校验函数实现
export const validateEmail = (input: string): ValidatedEmail | Error => {
  // 校验逻辑同上
  if (!校验通过) return new Error('非法邮箱');
  // 仅该函数可做该类型断言,外部无法模仿
  return {
    address: input,
    validatedOn: new Date()
  } as ValidatedEmail;
};

注意事项

  • 所有标记用的Symbol、私有类型都不要对外导出,保证只有校验函数所在的模块可以访问
  • 对安全性要求高的场景,建议加上运行时校验,避免有人绕过TS类型检查传入伪造实例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 09:54:03