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

如何让TypeScript对结构兼容的不同类型赋值触发报错?

让TypeScript拒绝超类型赋值的几种方法

由于TypeScript采用结构类型系统,当user2是user的超集(包含user的所有属性)时,默认允许将user2类型的变量赋值给user类型变量。要触发错误,可以通过以下几种方式实现名义类型的效果(让TypeScript不再只看结构,而是区分类型本身):

方法一:使用类+私有属性

类中的私有成员会被TypeScript的类型检查视为类型的一部分,即使两个类型结构相似,只要包含私有成员,就会被判定为不兼容。

class User {
  // 仅用于区分类型的私有属性,无需实际使用
  private _typeMarker: void;
  name: string;

  constructor(name: string) {
    this.name = name;
  }
}

interface User2 {
  name: string;
  numberOrNull: number | null;
}

let usr: User = new User("hey");
let usr2: User2 = { name: "as", numberOrNull: 12 };

usr = usr2; // TypeScript报错:类型"User2"缺少类型"User"中的私有属性"_typeMarker"

方法二:品牌类型(Branded Types)

通过给类型附加一个唯一的符号属性作为"品牌",让TypeScript识别出不同类型的区别。

// 定义品牌类型工具
type Brand<T, BrandName> = T & { readonly [Symbol.toStringTag]: BrandName };

// 给User添加品牌标记
type User = Brand<{ name: string }, "User">;
type User2 = { name: string; numberOrNull: number | null };

// 创建User类型变量时必须带上品牌属性(可通过类型断言简化)
let usr: User = { name: "hey", [Symbol.toStringTag]: "User" } as User;
let usr2: User2 = { name: "as", numberOrNull: 12 };

usr = usr2; // TypeScript报错:类型"User2"中缺少属性"[Symbol.toStringTag]"

方法三:通过泛型约束强制无多余属性

利用泛型和条件类型,限制赋值的类型不能包含User之外的属性:

interface User { name: string }
interface User2 { name: string; numberOrNull: number | null }

// 辅助函数:仅接受无多余属性的User类型
function strictAssignUser<T extends User>(
  user: Exclude<keyof T, keyof User> extends never ? T : never
): User {
  return user;
}

let usr2: User2 = { name: "as", numberOrNull: 12 };
let usr: User = strictAssignUser(usr2); // TypeScript报错:类型"User2"不能赋值给类型"never"

以上方法中,前两种(类私有属性、品牌类型)是最常用且稳定的方案,能有效让TypeScript拒绝超类型的赋值操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 02:17:43