首页 > 解决方案 > 对象相等比较打字稿。无法将 Object 属性应用于泛型类型

问题描述

为了更好地理解 Javascript 中的对象比较,以及使用 typescript 的属性访问,我试图从这个起点为我的班级制作一个 Equal 比较器。

TypeScript:对象相等比较(对象等于对象)

我知道这可以通过 stringify 和 loadash 来完成,但我发现深入研究对象属性以应用逻辑很有趣。

这是比较两个对象的代码(来自上面的链接):

private equals<T>(x: T, y: T): boolean {
    if (x === y) {
      return true; // if both x and y are null or undefined and exactly the same
    }
    if (!(x instanceof Object) || !(y instanceof Object)) {
      return false; // if they are not strictly equal, they both need to be Objects
    }
    if (x.constructor !== y.constructor) {
      // they must have the exact same prototype chain, the closest we can do is
      // test their constructor.
      return false;
    }
    for (const p in x) {
      if (!x.hasOwnProperty(p)) {
        continue; // other properties were tested using x.constructor === y.constructor
      }
      if (!y.hasOwnProperty(p)) {
        return false; // allows to compare x[ p ] and y[ p ] when set to undefined
      }
      if (x[p] === y[p]) {
        continue; // if they have the same strict value or identity then they are equal
      }
      if (typeof (x[p]) !== 'object') {
        return false; // Numbers, Strings, Functions, Booleans must be strictly equal
      }
      if (!this.equals(x[p], y[p])) {
        return false;
      }
    }
    for (const p in y) {
      if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) {
        return false;
      }
    }
    return true;
  }

我的问题是我无法访问 Object 属性构造函数和 hasOwnProperty。我得到错误:

类型“Vec3”.ts(2339) 上不存在属性“hasOwnProperty”。

我试图实现接口:

interface ObjectPropertiesHandlable {
  constructor: void;
  hasOwnProperty: void;
}

这样private equals<T extends ObjectPropertiesHandlable>(x: T, y: T): boolean {我就可以在声明中修复编译错误。

但如果是这样,这里的论点将不适合:

    if (!this.equals(x[p], y[p])) {
        return false;
      }

由于 p 是类型const p: Extract<keyof Vec3, string>(通过 typescript intellisense onHover)

如果我用我的类类型替换泛型(它是一个Vec3类,但不相关),尽管它有一个构造函数,我仍然有错误:

类型“Vec3”.ts(2339) 上不存在属性“hasOwnProperty”。

类型“Vec3”.ts(2339) 上不存在属性“构造函数”。

如果我应用接口来避免对象属性错误,则会收到此错误:

在此处输入图像描述

标签: typescriptgenericsequals

解决方案


要使其工作,请尝试下一个代码:

type Indexed = {
  [index: string]: unknown
}

const equals = <T extends Indexed>(x: T, y: T) => {
  // ... your code
}

您只需向 TS 保证您的论点实际上是对象。

请看答案

更新 尝试:

type Indexed = {
  [index: string]: Indexed
}

我有点脏,但如果你能解释一下你想要达到的目标,也许我会提供更好的解决方案


推荐阅读