如何更改 TypeScript 中的只读属性? [英] How can I change a readonly property in TypeScript?

查看:34
本文介绍了如何更改 TypeScript 中的只读属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够为我的班级用户创建 readonly 属性(不是 getter),但我需要在内部更新它们;有没有办法做到这一点并允许在内部进行更改?(并确保 TypeScript 阻止大多数更改值的尝试)

I want to be able to make readonly properties (not getters) for users of my class, but I need to update them internally; is there a way to do this and allow to be changed internally? (and make sure TypeScript blocks most attempts to change the value)

(就我而言,它是一个游戏引擎,getter/setter [一般功能] 是一个糟糕的选择)

推荐答案

我知道实际上有 3 种方法.如果您有这样的课程:

There are actually 3 ways I know of. If you have a class like this:

class GraphNode {
    readonly _parent: GraphNode;
    add(newNode: GraphNode) { /* ...etc... */ }
}
var node = new GraphNode();

add() 函数中,您可以执行以下任一操作:

In the add() function you could do either:

  1. newNode[<any>'_parent'] = this; - 有效,但想法很糟糕.重构将打破这一点.

  1. newNode[<any>'_parent'] = this; - Works, but BAD IDEA. Refactoring will break this.

更新: 似乎 newNode['_parent'] = this; 现在可以在没有 TypeScript,但重构仍然会破坏它.

Update: Seems newNode['_parent'] = this; will work just fine now without <any> in newer versions of TypeScript, but refactoring will still break it.

最佳:创建一个内部接口(仅供您自己使用):

BEST: Create an INTERNAL interface (used by yourself only):

interface IGraphObjectInternal { _parent: GraphNode; }
class GraphNode implements IGraphObjectInternal {
    readonly _parent: GraphNode;
    add(newNode: GraphNode) { /* ...etc... */ }
}

现在你可以只做 (newNode)._parent = this; 并且重构也可以工作.唯一需要注意的是,如果您从命名空间导出您的类(使用内部接口 IMO 的唯一原因),您还必须导出该接口.出于这个原因,我有时会使用 #2 来完全锁定只有一个地方使用它的内部结构(而不​​是向全世界宣传),但通常 #3 如果我需要在许多其他位置引用许多属性来使用(以防我需要重构).

Now you can just do (<IGraphObjectInternal>newNode)._parent = this; and refactoring will also work. The only caveat is that if you export your class from a namespace (the only reason to use an internal interface IMO) you'll have to export the interface as well. For this reason, I sometimes will use #2 to completely lock down internals where there's only one place using it (and not advertise to the world), but usually #3 if I need to have many properties to work with referenced in many other locations (in case I need to refactor things).

你可能注意到我没有谈论 getter/setter.虽然可以只使用 getter 而不使用 setter,然后更新私有变量,但 TypeScript 并不能保护您!我可以轻松地执行 object['_privateOrProtectedMember'] = 任何内容 并且它会起作用.它不适用于 readonly 修饰符(在问题中).使用 readonly 修饰符可以更好地锁定我的属性(就在 TypeScript 编译器中工作而言),并且因为 JavaScript 没有 readonly 修饰符,我可以使用在 JavaScript 端(即在运行时)使用变通方法更新它们的各种方法.;)

You may notice I didn't talk about getters/setters. While it is possible to use only a getter and no setter, then update a private variable, TypeScript does not protect you! I can easily do object['_privateOrProtectedMember'] = whatever and it will work. It does not work for the readonly modifier (which was in the question). Using the readonly modifier better locks down my properties (as far as working within the TypeScript compiler is concerned), and because JavaScript doesn't have a readonly modifier, I can use various methods to update them with workarounds on the JavaScript side (i.e. at runtime). ;)

警告:正如我所说,这仅适用于 TypeScript.在 JavaScript 中,人们仍然可以修改您的属性(除非您仅将 getter 用于未公开的属性).

Warning: As I said, this only works within TypeScript. In JavaScript people can still modify your properties (unless you use getters only with non-exposed properties).

从 typescript 2.8 开始,您现在可以删除 readonly 修饰符:

Since typescript 2.8 you can now remove the readonly modifiers:

type Writeable<T> = { -readonly [P in keyof T]: T[P] };

以及可选修饰符:

type Writeable<T> = { -readonly [P in keyof T]-?: T[P] };

更多信息:改进了对映射类型修饰符的控制

这篇关于如何更改 TypeScript 中的只读属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆