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

如何让函数仅接收实现指定接口的类的实例?

解决方案

TypeScript采用结构类型系统(鸭子类型),只要对象的结构与接口匹配,就会被认为符合该接口——这就是为什么Class2虽未显式实现CanDo,却能传入doSomething的核心原因。要实现仅允许Class1实例调用的需求,有以下几种可行方案:

方案一:用私有成员标记接口

给CanDo接口添加私有属性,只有显式实现该接口的Class1能拥有这个私有成员,Class2无法模拟私有成员的结构,从而被TypeScript拦截:

interface CanDo {
  someProperty: any;
  private readonly _canDoMarker: never;
}

class Class1 implements CanDo {
  someProperty: any;
  private readonly _canDoMarker: never = undefined!;
}

class Class2 {
  someProperty: any;
}

function doSomething(arg: CanDo) {
  callOtherFunction(arg.someProperty);
}

const object1 = new Class1();
const object2 = new Class2();

doSomething(object1); // 正常执行
doSomething(object2); // 类型错误:Class2缺少私有属性_canDoMarker

方案二:直接指定参数类型为Class1

如果不需要保留接口的抽象性,最直接的方式是把doSomething的参数类型改为Class1,从根源上限制传入的实例:

interface CanDo {
  someProperty: any;
}

class Class1 implements CanDo {
  someProperty: any;
}

class Class2 {
  someProperty: any;
}

function doSomething(arg: Class1) { // 直接用Class1替代CanDo
  callOtherFunction(arg.someProperty);
}

const object1 = new Class1();
const object2 = new Class2();

doSomething(object1); // 正常执行
doSomething(object2); // 类型错误:Class2不能赋值给Class1类型

方案三:使用品牌类型(Brand Type)

给CanDo类型添加唯一的品牌属性作为类型标识,只有Class1显式实现这个属性,Class2因缺少该属性无法通过类型检查:

type CanDo = {
  someProperty: any;
  _brand: 'CanDo'; // 品牌标识
};

class Class1 implements CanDo {
  someProperty: any;
  _brand: 'CanDo' = 'CanDo';
}

class Class2 {
  someProperty: any;
}

function doSomething(arg: CanDo) {
  callOtherFunction(arg.someProperty);
}

const object1 = new Class1();
const object2 = new Class2();

doSomething(object1); // 正常执行
doSomething(object2); // 类型错误:Class2缺少_brand属性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 18:33:20