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

如何让TypeScript对类型别名参数倒置的函数调用触发报错?

解决TypeScript中同结构类型别名无法区分的问题

你遇到的情况其实戳中了TypeScript类型系统的核心特点——它默认采用结构类型系统,而非Java、C#这类语言常用的名义类型系统。简单来说,只要两个类型的结构完全一致,TypeScript就会判定它们等价,不管你给它们起了多么不同的别名。在你的代码里,first和second都是number的别名,结构完全重合,所以TypeScript会把它们当成同一个类型处理,自然不会在参数顺序颠倒时触发报错。

要实现你期望的“按类型名义区分”的效果,我们可以通过给类型添加**唯一标记属性(Branding)**来打破结构一致性,同时不影响代码的运行性能。这里有几种实用方案:

方案1:添加只读品牌属性(最常用)

通过交叉类型给每个类型别名附加一个唯一的、只读的品牌属性,让TypeScript识别出它们是不同的类型:

// 给每个类型添加唯一的类型标记(仅存在于类型层面)
type first = number & { readonly __brand: 'first' };
type second = number & { readonly __brand: 'second' };

// 编写转换函数,方便创建对应类型的值
const createFirst = (num: number): first => num as first;
const createSecond = (num: number): second => num as second;

// 使用示例
let f = createFirst(1);
let s = createSecond(2);

const func = (arg1: first, arg2: second) => { };
func(s, f); // 这里会触发报错!完全符合你的预期

这个方案的优势很明显:品牌属性是只读的,不会被意外修改;而且它仅存在于类型检查阶段,运行时不会产生额外的属性或性能开销。

方案2:用类实现名义类型

如果你可以接受运行时存在类实例,也可以通过类的私有属性来区分类型:

class First {
  // 私有属性会让TypeScript判定两个类结构不同
  private readonly _brand: undefined;
  constructor(public value: number) {}
}

class Second {
  private readonly _brand: undefined;
  constructor(public value: number) {}
}

let f = new First(1);
let s = new Second(2);

const func = (arg1: First, arg2: Second) => { };
func(s, f); // 报错:类型不兼容

TypeScript对私有属性有特殊处理逻辑:即使两个类的公开结构完全一致,只要它们包含私有属性,就会被判定为不同类型。

方案3:用枚举作为品牌标记

你也可以用枚举定义清晰的品牌值,让类型区分更直观:

enum TypeBrand {
  FirstType = 'first',
  SecondType = 'second'
}

type first = number & { readonly brand: TypeBrand.FirstType };
type second = number & { readonly brand: TypeBrand.SecondType };

const createFirst = (num: number): first => num as first;
const createSecond = (num: number): second => num as second;

let f = createFirst(1);
let s = createSecond(2);

const func = (arg1: first, arg2: second) => { };
func(s, f); // 触发报错

总的来说,核心思路就是打破两个类型的结构一致性,让TypeScript能识别它们的“名义差异”而非仅仅是结构。其中方案1是最轻量化的选择,适合大多数场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:35:01