我正在尝试扩展Date对象以添加有用的方法。
根据W3Schools的说法,这应该有效:
Date.prototype.removeTime = () => {
// some awesome code to remove the timestamp
}
但是Typescript抱怨removeTime
不是Date
对象的已知属性。(技术上是正确的(
所以,我尝试了这个:
Object.defineProperty(Date.prototype, "removeTime", {
enumerable: false,
configurable: false,
writable: false,
value: function() {
// Do some magic
return null;
}
});
但是,当在代码中使用它时:
类型"Date"上不存在属性"removeTime">
我不明白,因为我这样做是为了向数组原型添加一个方法,比如:
Object.defineProperty(Array.prototype, "unique", {
enumerable: false,
configurable: false,
writable: false,
value: function() {
const a = this.concat();
for (let i = 0; i < a.length; ++i) {
for (let j = i + 1; j < a.length; ++j) {
if (a[i] === a[j]) {
a.splice(j--, 1);
}
}
}
return a;
}
});
这是有效的,我可以在代码中使用它,Typescript没有抱怨。
我在这里错过了什么?为什么它对Array
有效而对Date
无效?
编辑:在阅读了评论之后,我决定采用一种方法:
removeTimeFromDate(date: Date): Date {
return new Date(date.getFullYear(), date.getMonth(), date.getDay());
}
这里有两种不同的东西:
-
添加运行时方法
-
添加类型信息
您所做的是添加运行时内容,但不是更新类型。
你可以添加这样的类型信息:
interface Date {
removeTime(): Date;
}
这增加了Date
接口。
(此外,在添加运行时方法时,请使用defineProperty
方法,而不是带有箭头函数的赋值。(
下面是一个完整的例子:
// Type
interface Date {
removeTime(): Date;
}
// Runtime
Object.defineProperty(Date.prototype, "removeTime", {
enumerable: false, // This is the default, you can leave it off if you like
configurable: true, // Normally, method properties are configurable
writable: true, // Normally, method properties are writable
value: function() {
// Do some magic
this.setHours(0, 0, 0, 0);
return this;
}
});
let d = new Date();
console.log(d.toISOString());
d.removeTime();
console.log(d.toISOString());
在操场上
FWIW,关于扩展内建的几个注意事项:
- 这通常不是将在您不直接控制的项目中使用的代码的最佳实践(您正在编写的用于他人项目的库代码等(
- 通常最好使用
defineProperty
来定义不可枚举的属性(不过通常是可写和可配置的( - 选择真正特定于您的项目的名称,这样,如果在规范的后面添加内建,您的名称就不太可能被使用。只是有可能在某个时候将
removeTime
方法添加到Date
中(尽管这不太可能(,但不可能添加myRemoveTime
方法