You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

TypeScript中参数类型不同却出现函数重复实现错误的原因与解决方法

为什么会出现这个错误?

这个问题其实和TypeScript的函数重载规则以及结构类型系统都有关系,咱们一步步拆解:

  1. 你写的不是正确的函数重载
    你现在的写法是直接定义了两个带函数体的同名方法,但在TypeScript中,类里的函数重载需要先声明重载签名(只定义参数和返回值,没有函数体),再写一个实现签名(包含函数体,参数类型要覆盖所有重载的情况)。直接写两个带函数体的同名方法,不管参数类型看起来多不一样,TypeScript都会把它们当成重复的函数实现。

  2. 结构类型系统的“隐性冲突”(如果Requirement和Policy结构兼容的话)
    TypeScript是结构类型系统,也就是说如果RequirementPolicy这两个类型的结构完全一致(比如都是空接口,或者拥有完全相同的属性、方法),那TypeScript会认为这两个类型是等价的。这种情况下哪怕你想做重载,也会因为签名本质重复而报错。


怎么解决?

分两种场景来处理:

场景1:Requirement和Policy是结构不同的类型

按照TypeScript正确的函数重载写法修改你的类:

class YourAuthClass {
  // 先声明两个重载签名(只有参数和返回值定义,无函数体)
  authorize(resource: any, requirement: Requirement): boolean;
  authorize(resource: any, policy: Policy): boolean;

  // 再写统一的实现签名(参数类型要覆盖所有重载的可能)
  authorize(resource: any, rule: Requirement | Policy): boolean {
    // 根据参数类型分支处理逻辑
    if (rule instanceof Requirement) {
      // 处理Requirement类型的逻辑
      return false;
    } else if (rule instanceof Policy) {
      // 处理Policy类型的逻辑
      return false;
    }
    return false;
  }
}

如果RequirementPolicy是接口(而非类),instanceof无法判断类型,这时候可以给它们加一个独特的标识属性来区分:

interface Requirement {
  type: 'requirement';
  // 其他属性...
}

interface Policy {
  type: 'policy';
  // 其他属性...
}

// 实现里通过标识判断类型
authorize(resource: any, rule: Requirement | Policy): boolean {
  if (rule.type === 'requirement') {
    // 处理Requirement逻辑
  } else {
    // 处理Policy逻辑
  }
  return false;
}

场景2:Requirement和Policy结构完全一致

如果这两个类型结构一模一样,TypeScript确实没法区分它们的重载,这时候有两个可选方案:

  • 给其中一个类型添加独特属性,让它们结构产生差异(比如上面的type标识)
  • 改用不同的方法名,比如authorizeWithRequirementauthorizeWithPolicy,从根源上避免同名冲突

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

火山引擎 最新活动