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

TypeScript如何在编译阶段阻止结构兼容的类实例非法传入?

TypeScript编译阶段阻止结构兼容类实例传入

问题描述

当两个类拥有相同的属性和方法时,TypeScript允许传入方法签名中未指定的类实例,如何在编译阶段(而非运行时通过instanceof检查)阻止这种情况?

示例代码:

abstract class Base {
  abstract display(): void;
}

class Person extends Base {
  override display(): void {
    console.log('I am a person');
  }
}

class Animal extends Base {
  override display(): void {
    console.log('I am an animal');
  }
}

const display = function (value: Person) {
  value.display();
};

display(new Person());
display(new Animal()); // 此处期望编译阶段报错,但并未报错

同时确认:TypeScript是否基于类的方法和属性(而非类名称/引用)进行类型检查?


解答

1. TypeScript的类型检查逻辑

是的,TypeScript采用结构类型系统:只要两个类型的结构(属性、方法的名称与类型)完全匹配,就会被视为类型兼容,不管它们的类继承关系或类名是否一致。这就是示例中Animal实例能被传入期望Person的函数的原因——两者结构完全相同。

2. 编译阶段的解决方案

要在编译阶段阻止这种情况,核心是给不同类添加唯一的结构标识,让TypeScript认为它们的结构不兼容,具体有两种常用方式:

方式一:添加私有/保护成员

给类添加私有(private)或保护(protected)的属性/方法,私有成员属于特定类,无法被其他类继承或匹配,从而打破结构兼容性。

修改后的代码:

abstract class Base {
  abstract display(): void;
}

class Person extends Base {
  private _personFlag: void; // 添加私有标识成员
  override display(): void {
    console.log('I am a person');
  }
}

class Animal extends Base {
  private _animalFlag: void; // 添加私有标识成员
  override display(): void {
    console.log('I am an animal');
  }
}

const display = function (value: Person) {
  value.display();
};

display(new Person());
display(new Animal()); // 编译阶段报错:类型“Animal”的参数不能赋给类型“Person”的参数。属性“_personFlag”在类型“Animal”中缺失,但在类型“Person”中是必需的。
方式二:使用品牌类型(Branded Types)

给类添加只读的、类型为唯一字面量的属性,让不同类的结构因该属性类型不同而不兼容。

修改后的代码:

abstract class Base {
  abstract display(): void;
}

class Person extends Base {
  readonly type: 'Person' = 'Person'; // 品牌标识
  override display(): void {
    console.log('I am a person');
  }
}

class Animal extends Base {
  readonly type: 'Animal' = 'Animal'; // 品牌标识
  override display(): void {
    console.log('I am an animal');
  }
}

const display = function (value: Person) {
  value.display();
};

display(new Person());
display(new Animal()); // 编译阶段报错:类型“Animal”的参数不能赋给类型“Person”的参数。类型“"Animal"”不能赋给类型“"Person"”。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 12:50:12