我正在尝试将一些 JavaScript 代码移植到 TypeScript。
其中一个类如下所示(游乐场链接):
class Foo {
constructor() {
Object.defineProperties(this, {
a: {
value: 'a',
},
b: {
value: 'b',
},
n: {
writable: true,
value: 0,
},
});
assertFooApi(this);
}
reset() {
this.a = 'a';
this.b = 'b';
this.n = 0;
}
}
interface FooApi {
a: string,
b: string,
n: number,
}
function assertFooApi(input: any): asserts input is FooApi {
// intentionally fake
}
此reset
函数会出错,因为Object.defineProperties
它不会影响 typescript 中的类型签名。
我没有编写原始 JavaScript 代码,也没有完全理解它。我正在寻找一种方法来定义 的this
类型而不修改任何行为。我对其现有实现所做的更改越少越好。最终,我将围绕它编写自动化测试,以便我可以更改其实现,但作为第一步,我认为将其移植到打字稿是最划算的。
此评论提供了解决该问题的两种方法。我认为如果我不需要将解决方法应用于this
. 但正如您所看到的(在上面的游乐场链接中),使用断言函数this
不会修改其内部类型。
如果一个类在this
with上定义了属性Object.defineProperties
,我如何在其他内部函数中使用这些属性而不出现编译错误?
这正是关键字的作用
declare
。它创建类型信息但从不发出任何代码。它很少在生产代码中使用,因为它很容易让您在某些东西的真正类型上撒谎。但是,对于这样的情况,您可以添加属性,
declare
告诉类型系统期望它们在那里。重要提示:请小心!如果您更改代码
defineProperties
以创建不同的属性,打字稿无法将其配对并引发类型错误。这可能会导致运行时崩溃。这不是一个正确的解决方案。但是,当将非类型化代码逐步移植到类型化代码时,有时这种不安全性是一种改进。查看游乐场
要将此代码转换为 TS 而不改变其行为,
declare
类字段(declare
d 字段编译为空)readonly
不可写字段implement
您的界面以确保其正确实施请记住,构造函数的返回值类型不会以任何方式影响类类型。只有字段、方法和
extends
子句可以。我想这算是一个答案,但我希望有更好的答案。如果您像这样实现
reset
,错误就会消失(游乐场链接):理想情况下,我不必将其放在每个内部函数的顶部。