typescript - TypeScript:在类中标记为只读的属性实际上被覆盖
问题描述
我正试图围绕 TypeScript 中的readonly关键字。据我了解,在调用构造函数后,只读属性将不可写,但当我测试时,我实际上可以覆盖它。编译器给出了有关“无法分配给 'doNoTChange' 因为它是一个只读属性”和“属性 'doNoTChange' 是私有的并且只能在类 'readOnlyClass' 中访问”的错误,但无论如何代码都会被编译并运行。所以我的问题是,这是正常的吗?有没有办法防止覆盖?
我在 Vue 中使用 TypeScript,只是为了澄清。
这是我正在测试的实际代码。我正在 App.vue 文件的挂载钩子中进行测试(即,我没有更改 Vue CLI 给出的默认文件结构)
使用Vue 2.6.11和TypeScript 3.5.3 版
mounted() {
/** Class definition */
class readOnlyClass {
readonly doNoTChange: string;
constructor(ss: string) {
this.doNoTChange = ss;
}
}
/** Creating and loggin object */
let test = new readOnlyClass('aaa');
console.log(test.doNoTChange); // outputs 'aaa'
/** Overwritting and logging the changed property */
test.doNoTChange = 'after change';
console.log(test.doNoTChange); // outputs 'after change'
}
解决方案
当您使用 编译 TypeScript 代码时tsc
,它会进行类型检查和转译为 JavaScript,这些在很大程度上是相互独立的。
编译器会进行类型检查以向开发人员提供警告,如果他们正在做一些可能导致运行时出现问题的潜在错误。请注意,这些实际上只是警告;它们实际上并不能防止运行时出现问题。因此,当您分配给readonly
属性时,您会收到所需的警告:
Cannot assign to 'doNoTChange' because it is a read-only property.(2540)
这告诉您您可能想要解决问题。它本身并不能解决问题(这可能需要比合理编程到编译器中更多的智能)并编译没有问题的代码版本。
编译器通过擦除静态类型系统功能并在编译器选项指定的任何目标 JavaScript 版本中输出剩余的运行时代码来生成 JavaScript。这意味着readonly
,纯类型系统功能根本不会出现在运行时代码中。你不会在 JavaScript 中找到它。无论类型检查器发现多少错误,编译器都可以发出 JavaScript。那是故意的。
如果您希望编译器在出现错误时不发出 JavaScript,您可以使用编译--noEmitOnError
器选项。如果你不能让它工作,你应该三重检查你的编译器配置并考虑生成一个可重现的示例,以便其他人可以看到同样的问题。
备份,您遇到的问题通常可能与类型擦除有关。在 TypeScript 中,如果您想到自己想要的运行时代码,然后使用 TypeScript 为该代码提供更强大的类型,那么您通常会更开心,这样您在编写代码时就可以得到 IDE 的一些指导。x.toUpperCase()
在运行时,无论是什么,JavaScript 都会愉快地尝试评估x
。如果您编写let x: string;
,然后稍后x = 15; x.toUpperCase()
,编译器将警告您x = 15
您正在为自己设置一个问题。
那么,哪些运行时代码会表现得如您所愿?一个可能的候选者是对属性使用JavaScript getter 。doNoTChange
如果你创建了一个没有 setter 的 getter,那么当你尝试设置属性时会出现运行时错误。代码可能会更改为:
class readOnlyClass {
private _val: string;
get doNoTChange(): string {
return this._val;
}
constructor(ss: string) {
this._val = ss;
}
}
--target
如果您是,则编译为以下代码ES2017
:
class readOnlyClass {
constructor(ss) {
this._val = ss;
}
get doNoTChange() {
return this._val;
}
}
然后你会得到这种行为:
let test = new readOnlyClass('aaa');
console.log(test.doNoTChange); // outputs 'aaa'
test.doNoTChange = 'after change'; // compile error here, and at runtime:
// TypeError: setting getter-only property "doNoTChange"
console.log(test.doNoTChange);
编译器错误和运行时错误。
好的,希望能给你一些方向;祝你好运!
推荐阅读
- bash - 带有 for 循环的无效算术运算符(错误标记为“”)
- python - 使用并行运行 html2text
- akka - 有没有办法让一个 Akka 节点知道另一个 Akka 节点是否重新启动
- vba - 尽管计算设置为手动,但在打开工作簿时不会禁用计算
- visual-studio-code - 每次在 VS Code 中打开新的终端窗口时,如何运行一些命令?
- javascript - AWS IoT Core 连接被经过身份验证的 Cognito 用户拒绝,带有附加策略 [MQTT over WSS]
- sql - 使用命令复制在 postgres 中出现变量连接问题
- android - Android Intent Share 无法正常工作
- corda - 使用 network-bootstrapper 生成节点信息需要带有 devMode=false 的证书
- php - 由于 .htaccess,php curl 出现 301 错误