所以我试图扩展对象类。之所以是因为我想写一个函数叫isEqual
isEqual(object: any): boolean {
return JSON.stringify(this) === JSON.stringify(object);
}
我尝试扩展 Object,但没有泛型类型。
我知道我可以使用一个带有两个参数并检查它的函数。但我想学习如何在 Typescript 中做到这一点。
我在 StackOverflow 上读到运算符重载是不可能的(因为最初我想使用 == 运算符来调用上面的函数)。
有人可以帮助我吗?
最佳答案
您希望向 the global Object
type 的所有实例添加 isEqual()
方法。在 JavaScript 中,这可以通过将方法添加到 Object.prototype
来完成,并且对象的所有实例都将 inherit the method automatically .
在我说如何做之前,几乎普遍认为修改这样的原生原型(prototype)是一个坏主意。请参阅Why is extending native objects a bad practice?有关于此的官方 SO 答案。但简单地说:将 Object.prototype
视为 common property这需要每个人分享。如果您开始对其进行更改,而其他代码不需要这些更改,则该代码可能无法正常运行。相反,某些其他代码可能会进行更改,从而导致您的更改无法正常运行。
向Object.prototype
添加方法的简单方法,例如Object.prototype.isEqual = ...
或Object.defineProperty(Object.prototype , 'isEqual', {value(...){...}})
最终会将 isEqual
作为 enumerable property所有对象,这意味着 for...in
loop会突然显示 "isEqual"
作为到处可能的对象的键。
这里的官方建议是不要这样做。
如果您仍然想这样做(例如,也许您正在使用其他人不需要与之交互的代码来执行此操作,因此唯一可能受到此伤害的人就是您),那么这里是如何操作的。 TypeScript 支持declaration merging允许添加现有接口(interface):
interface Object {
isEqual(object: object): boolean;
}
如果您这样写,编译器现在会期望所有 Object
都具有 isEqual()
方法。 (如果您的代码位于模块中,则需要将其包装在 declare global { }
block 中,称为 global augmentation )。
当然你还得实现它:
Object.defineProperty(Object.prototype, 'isEqual', {
value(object: object) {
return JSON.stringify(this) === JSON.stringify(object);
},
configurable: true,
enumerable: false // <-- we don't want to mess with for...in loops
});
这里我使用了the Object.defineProperty()
method这样我们就可以显式地阻止方法名称可枚举。
现在您可以验证它是否按预期工作:
interface Foo { a: number, b: string };
const o1: Foo = { a: 1, b: "two" };
const o2: Foo = { b: "two", a: 1 };
console.log(o1.isEqual(o2)); // false
o1.isEqual(o2)
编译时没有错误,当您运行它时,它会使用您的 isEqual()
方法,并返回 false
正如预期的那样。 (您确实期望错误
,对吗?如果没有,请参阅sort object properties and JSON.stringify。)
关于javascript - 在 Typescript 中扩展 {}(对象),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74000085/