问题:
当前,可以通过简单的赋值操作将一个方法(使用 ES6 method syntax 编写的函数)替换为另一个函数。例如,考虑以下代码片段:
class Person {
constructor(...) {...}
displayName (): string {...}
}
const x: Person = new Person(...)
x.displayName = function(this: Person): string {...} // Assignment
由于 readonly
修饰符不能用于方法,因此无法防止这种赋值操作。
建议:
方法始终是只读的。
以下代码完全相同:
class Person {
displayName (): string {...}
}
class Person {
readonly displayName: (this: Person) => string = function () {...}
}
兼容性:
这是一个破坏性更改。然而,方法语法是最近才出现的,并且主要在类中使用。将函数赋值给方法的代码肯定是很少见的。
临时解决方法:
不要在你的类和接口中使用方法语法。请注意,这会导致非常冗长的代码。
如果你使用接口,那么冗长是可以接受的。但是你也会遇到严格的协变性问题。
interface PersonI {
readonly displayName: (this: Person) => string
}
9条答案
按热度按时间rbl8hiat1#
相关讨论:#58296 (评论)
qaxu7uf22#
我想要添加一个功能,即在方法事件中处理只读Map类型,如果不允许使用只读关键字。
一个严格伞形下的标志,默认将所有方法设置为只读,并强制使用属性函数来处理“可分配方法”,这也是受欢迎的。
nzrxty8p3#
@feeddageek It's allowed when you store method as arrow function class property:
moiiocjp4#
另一个解决方法(基于@feeddageek的想法)是强制使用一个返回对象“只读版本”的工厂:
注意,所有属性也都变为只读。
然而,如果TypeScript初学者阅读这段代码,他们可能会认为对象不能被改变(如果对象有可变方法,情况并非如此)。
5cg8jx4n5#
@patrykuszynski 使用只读函数属性的问题在于它们不会在原型上编译,而是由构造函数构建到示例中。
此外,它们捕获了它们的
this
,而传统方法则没有。(通过使用函数表达式而不是箭头函数来防止捕获
this
可以解决这个问题,但这不是重点)更正:
test2.inProto = test1.inProto;
实际上确实做了一些事情,但与手头的事情关系不大。9rygscc16#
这也是一个关于命名空间的问题。允许使用const/readonly会使代码更简洁,将其设为默认值可以防止库作者在实现被替换时感到惊讶。
$x_1^a_0b_1^x$
ulmd4ohb7#
然而,这将破坏声明合并/模块增强,因为你不能在环境上下文中定义函数。
92vpleto8#
FYI, I filed #47003 which is basically the same request, and Ryan replied with a pointer to this issue and a comment that there hasn't been much interest so at this point action is unlikely. It occurred to me that the bar is probably lower to make a linter rule, which I think could be just as effective at catching accidental assignments as a language-level "readonly" modifier. I haven't asked yet but if I do I'll make sure to ping this issue.
wtzytmuj9#
我非常希望看到这种情况发生,因为当启用https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.md时,使用一个或多个方法作为函数参数的类会导致linter错误。
将类属性设置为不可变,但方法不能这样做,这也相当不一致。