对象相等比较打字稿。无法将对象属性应用于泛型类型
Object equality comparison typescript. Cannot apply Object properties to generic type
为了更好地理解 Javascript 中的对象比较,以及使用打字稿的 属性 访问,我试图从这个起点为我的 class 创建一个 Equal 比较器。
我知道这可以通过 stringify 和 loadash 完成,但我发现深入研究对象属性以应用逻辑很有趣。
这是比较两个对象的代码(来自上面的link):
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;
}
我的问题是我无法访问对象属性构造函数和 hasOwnProperty。我收到错误:
Property 'hasOwnProperty' does not exist on type 'Vec3'.ts(2339).
我尝试实现接口:
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)
如果我用我的 class 类型替换泛型(它是 Vec3
class,但不相关)尽管它有一个构造函数,但我仍然有错误:
Property 'hasOwnProperty' does not exist on type 'Vec3'.ts(2339).
Property 'constructor' does not exist on type 'Vec3'.ts(2339).
如果我应用一个接口来避免对象 属性 错误,我得到这个错误:
要让它工作,请尝试下一个代码:
type Indexed = {
[index: string]: unknown
}
const equals = <T extends Indexed>(x: T, y: T) => {
// ... your code
}
你应该向 TS 保证你的参数实际上是对象。
请看
更新
尝试:
type Indexed = {
[index: string]: Indexed
}
我觉得有点脏,但如果你能解释一下你想达到什么目的,也许我会提供更好的解决方案
为了更好地理解 Javascript 中的对象比较,以及使用打字稿的 属性 访问,我试图从这个起点为我的 class 创建一个 Equal 比较器。
我知道这可以通过 stringify 和 loadash 完成,但我发现深入研究对象属性以应用逻辑很有趣。
这是比较两个对象的代码(来自上面的link):
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;
}
我的问题是我无法访问对象属性构造函数和 hasOwnProperty。我收到错误:
Property 'hasOwnProperty' does not exist on type 'Vec3'.ts(2339).
我尝试实现接口:
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)
如果我用我的 class 类型替换泛型(它是 Vec3
class,但不相关)尽管它有一个构造函数,但我仍然有错误:
Property 'hasOwnProperty' does not exist on type 'Vec3'.ts(2339).
Property 'constructor' does not exist on type 'Vec3'.ts(2339).
如果我应用一个接口来避免对象 属性 错误,我得到这个错误:
要让它工作,请尝试下一个代码:
type Indexed = {
[index: string]: unknown
}
const equals = <T extends Indexed>(x: T, y: T) => {
// ... your code
}
你应该向 TS 保证你的参数实际上是对象。
请看
更新 尝试:
type Indexed = {
[index: string]: Indexed
}
我觉得有点脏,但如果你能解释一下你想达到什么目的,也许我会提供更好的解决方案