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

TypeScript访问者模式下类型信息丢失问题求助

解决TypeScript访问者模式中类型信息丢失问题

在JavaScript中,typeof操作符对于类实例始终返回object——因为TypeScript的类编译后本质是基于原型的构造函数,实例都是对象类型。所以你用typeof无法区分Person和Address实例,以下是几种可行的解决方案:

方案1:使用constructor.name获取类名

每个类实例的constructor属性指向其构造函数,而构造函数的name属性就是类的名称(编译后的JavaScript会保留类名,除非代码被压缩混淆)。修改你的访问者代码:

class StrVisitor extends AbsVisitor
{
  public visitPerson(p: Person): void {
    console.log(`XXX ${p.constructor.name}  XXX`) // 输出"Person"
    console.log(`name: ${p.name}`);
  }
  public visitAddress(a: Address): void {
    console.log(`XXX ${a.constructor.name}  XXX`) // 输出"Address"
    console.log(`{${a.street}}( ${a.num} )`);
  }
}

运行后结果会变成:

XXX Person  XXX
name: moish
XXX Address  XXX
{5th Ave.}( 62 )

方案2:添加自定义类型标识字段

如果担心代码压缩导致类名被混淆(比如生产环境打包工具会重命名类),可以给每个类添加一个硬编码的类型标识属性:

class Person {
  readonly type = 'Person'; // 自定义类型标识
  constructor(public name: string){}
  public accept(v: AbsVisitor){ v.visitPerson(this); }
}

class Address {
  readonly type = 'Address'; // 自定义类型标识
  constructor(public street: string, public num: number){}
  public accept(v: AbsVisitor){ v.visitAddress(this); }
}

然后在访问者中直接读取该属性:

class StrVisitor extends AbsVisitor
{
  public visitPerson(p: Person): void {
    console.log(`XXX ${p.type}  XXX`) // 输出"Person"
    console.log(`name: ${p.name}`);
  }
  public visitAddress(a: Address): void {
    console.log(`XXX ${a.type}  XXX`) // 输出"Address"
    console.log(`{${a.street}}( ${a.num} )`);
  }
}

这种方法的优势是类型标识完全可控,不受编译或压缩工具的影响,同时TypeScript还能基于这个字段做类型窄化判断。

方案3:利用TypeScript元数据(进阶)

如果你需要更复杂的类型信息,可以启用TypeScript的装饰器和元数据功能:

  1. 在tsconfig.json中启用experimentalDecorators和emitDecoratorMetadata
  2. 使用reflect-metadata库获取类的元数据

不过这种方法相对复杂,适合需要深度类型反射的场景,普通场景前两种方案足够。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 08:45:29