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

为何Equal类型工具中Point构造函数类型与PointConstructor接口不相等?

为什么自定义Equal类型判断typeof Point和PointConstructor不相等,但双向extends都为true?

先看复现代码:

type Equal<A, B> = (<T>() => T extends A ? 1 : 0) extends <T>() => T extends B
  ? 1
  : 0
  ? true
  : false

class Point {
  x: number
  y: number

  constructor(x: number, y: number) {
    this.x = x
    this.y = y
  }
}
interface PointConstructor {
  new (x: number, y: number): Point
}

type bo = Equal<typeof Point, PointConstructor> // type bo = false
type bo1 = typeof Point extends PointConstructor ? true : false // type bo1 = true
type bo2 = PointConstructor extends typeof Point ? true : false // type bo2 = true

核心原因拆解

  1. 两个类型的本质差异
    typeof Point是TypeScript自动推导的类构造函数类型,它除了包含new(x: number, y: number): Point的构造签名,还隐含了类的静态成员(比如默认存在的prototype属性);而PointConstructor是你手动定义的接口,只包含构造签名这一个成员。

  2. 双向extends的兼容性逻辑
    TypeScript的结构类型系统中,extends做的是成员兼容性检查:

  • typeof Point extends PointConstructor为true:因为typeof Point包含了PointConstructor要求的所有必要成员(构造签名),满足子类型兼容父类型的规则。
  • PointConstructor extends typeof Point为true:当接口extends类构造函数类型时,TypeScript会忽略类构造函数类型中的静态成员,只校验构造签名的一致性,两者构造签名完全匹配,因此判定兼容。
  1. Equal类型的严格相等逻辑
    自定义的Equal类型利用了函数类型的逆变特性实现严格相等判断:它把A和B放到泛型函数返回值的条件类型中,通过比较两个函数类型是否完全兼容,来判断原类型是否严格相等。
    由于typeof Point比PointConstructor多了静态成员,两者作为泛型约束时的范围并不完全一致,导致对应的函数类型不兼容,最终Equal返回false。

简单总结:双向extends是宽松的结构兼容性检查,只要必要成员匹配就通过;而Equal是严格的全量类型相等检查,要求两个类型的所有细节(包括隐含成员)完全一致才会返回true。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:42:37