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

TypeScript:如何标记类为不可引用比较并触发警告?

在TypeScript中标记类禁止引用比较的方案

要实现禁止对特定类的实例使用==或===比较,同时触发类型错误/警告,有以下几种实用方案:

1. 类型层面:重写valueOf返回never类型

利用TypeScript的类型检查机制,让类的valueOf方法返回never类型。因为==比较会隐式调用valueOf,当返回值是never时,任何引用比较都会触发类型错误,同时运行时也能抛出错误提醒。

示例代码:

class CloneableEntity {
  constructor(public id: string, public name: string) {}

  // 重写valueOf,返回never类型并抛出运行时错误
  valueOf(): never {
    throw new Error('禁止使用==/===进行引用比较,请使用equals方法');
  }

  // 自定义相等判断方法
  equals(other: CloneableEntity): boolean {
    return this.id === other.id && this.name === other.name;
  }
}

// 类型错误:类型never不能与类型CloneableEntity进行比较
const a = new CloneableEntity('1', 'foo');
const b = new CloneableEntity('1', 'foo');
console.log(a === b); // 编译报错,运行时执行也会抛错
console.log(a.equals(b)); // 正确用法,返回true

2. ESLint自定义规则:静态检测引用比较

如果需要在代码审查阶段就拦截这类问题,可以自定义ESLint规则,检测对目标类实例使用==/===的情况,直接抛出警告或错误。

核心思路是遍历AST,识别BinaryExpression节点(即比较表达式),判断两边的表达式是否为目标类的实例,若是则触发规则报错。

示例规则片段(简化版):

module.exports = {
  create(context) {
    return {
      BinaryExpression(node) {
        if (['==', '===', '!=', '!=='].includes(node.operator)) {
          // 检查左右操作数是否为CloneableEntity的实例
          const isTargetClass = (expr) => 
            expr.type === 'NewExpression' && expr.callee.name === 'CloneableEntity' ||
            expr.type === 'Identifier' && context.getScope().variables.some(v => v.type === 'Class' && v.name === 'CloneableEntity');
          
          if (isTargetClass(node.left) || isTargetClass(node.right)) {
            context.report({
              node,
              message: '禁止对CloneableEntity实例使用引用比较,请使用equals方法'
            });
          }
        }
      }
    };
  }
};

3. 运行时防护:重写Symbol.toPrimitive

除了valueOf,还可以重写Symbol.toPrimitive,彻底拦截隐式类型转换时的引用比较,确保即使绕过类型检查(比如用any类型),运行时也能阻止错误比较。

示例代码:

class Uncomparable {
  constructor(public data: Record<string, any>) {}

  [Symbol.toPrimitive](): never {
    throw new Error('禁止使用引用比较,请使用equals方法');
  }

  equals(other: Uncomparable): boolean {
    return Object.keys(this.data).every(key => this.data[key] === other.data[key]);
  }
}

// 即使强制转为any,运行时也会抛错
const x = new Uncomparable({ a: 1 });
const y = new Uncomparable({ a: 1 });
console.log((x as any) === (y as any)); // 运行时抛出错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 01:24:26