Typescript 4:临时覆盖原型方法
Typescript 4: Temporary overriding of a prototype method
下一个代码在 typescript 3.3.3 上运行(在 repl.it 上)。它会在每次其他调用时覆盖或恢复为原型的方法。
class Foo {
foo () {
this.foo = function() {
console.log('instance call')
delete this.foo // ⟵ Compilation problem with TS4 here
}
console.log('prototype call')
}
}
const f = new Foo()
f.foo()
f.foo()
f.foo()
f.foo()
输出为:
prototype call
instance call
prototype call
instance call
但是此代码无法在 typescript 4 上编译。删除行发出“'delete' 运算符的操作数必须是可选的。”错误。
有什么方法可以解决这个特定的编译问题吗?
可能会有细微的变化,因为我经常使用这种范式。
TypeScript 4.0 添加了 you may only delete
properties that are optional 的限制。由于 foo
属性 或 Foo
是必需的,因此您不能 delete
它。从原型中也存在的实例中删除某些东西的用例可能没有被考虑,或者认为不够重要。
通常解决此问题的一种方法是使 foo
方法可选,如下所示:
class Foo {
foo?() {
this.foo = function () {
console.log('instance call')
delete this.foo
}
console.log('prototype call')
}
}
const f = new Foo()
if (f.foo) f.foo()
if (f.foo) f.foo()
if (f.foo) f.foo()
if (f.foo) f.foo()
但这可能不是您想做的,因为您知道foo
将始终存在于继承链的某处。
相反,您可以在 delete
语句中使用 type assertion 来告诉编译器将 this
视为其 foo
属性 是可选的:
class Foo {
foo() {
this.foo = function () {
console.log('instance call')
delete (this as Partial<Foo>).foo
}
console.log('prototype call')
}
}
const f = new Foo()
f.foo()
f.foo()
f.foo()
f.foo()
下一个代码在 typescript 3.3.3 上运行(在 repl.it 上)。它会在每次其他调用时覆盖或恢复为原型的方法。
class Foo {
foo () {
this.foo = function() {
console.log('instance call')
delete this.foo // ⟵ Compilation problem with TS4 here
}
console.log('prototype call')
}
}
const f = new Foo()
f.foo()
f.foo()
f.foo()
f.foo()
输出为:
prototype call
instance call
prototype call
instance call
但是此代码无法在 typescript 4 上编译。删除行发出“'delete' 运算符的操作数必须是可选的。”错误。
有什么方法可以解决这个特定的编译问题吗? 可能会有细微的变化,因为我经常使用这种范式。
TypeScript 4.0 添加了 you may only delete
properties that are optional 的限制。由于 foo
属性 或 Foo
是必需的,因此您不能 delete
它。从原型中也存在的实例中删除某些东西的用例可能没有被考虑,或者认为不够重要。
通常解决此问题的一种方法是使 foo
方法可选,如下所示:
class Foo {
foo?() {
this.foo = function () {
console.log('instance call')
delete this.foo
}
console.log('prototype call')
}
}
const f = new Foo()
if (f.foo) f.foo()
if (f.foo) f.foo()
if (f.foo) f.foo()
if (f.foo) f.foo()
但这可能不是您想做的,因为您知道foo
将始终存在于继承链的某处。
相反,您可以在 delete
语句中使用 type assertion 来告诉编译器将 this
视为其 foo
属性 是可选的:
class Foo {
foo() {
this.foo = function () {
console.log('instance call')
delete (this as Partial<Foo>).foo
}
console.log('prototype call')
}
}
const f = new Foo()
f.foo()
f.foo()
f.foo()
f.foo()