【问题标题】:Defining constant/ro properties on objects with TypeScript使用 TypeScript 在对象上定义常量/ro 属性
【发布时间】:2018-07-18 06:43:11
【问题描述】:

使用 TypeScript,有没有办法强制不重新分配?

说我有这个:

fn.foo = 5;
fn.foo = 6;

有没有办法让第二行出现编译错误?一旦我分配了 foo 属性,我想它应该是ReadOnly。

我的案例 foo 可以坚持这个界面:

export interface RO {
  [readonly key: string]: any
}

但我不确定该语法是否有效。

【问题讨论】:

  • fn 的类型是什么?
  • fn 可以是任何对象,我可以控制它的源代码

标签: typescript tsc


【解决方案1】:

如果你使用一个类,你可以将字段本身标记为readonly,你只能在构造函数中赋值:

class Test {
    readonly foo : string;
    constructor () {
        this.foo = "";
    }
}

let fn = new Test();
fn.foo = "" // Error 

如果你使用对象字面量,你可以使用显式类型来不允许字段的突变,只是它的初始赋值:

let fn : {
    readonly foo: string
} = {
    foo: "1"
}

您也可以使用Object.freeze,它也具有运行时行为:

let fn  = Object.freeze({
    foo: "1"
})
fn.foo = "" // error

在任何一种情况下,您都可以创建一个 readonly 字段,该字段只能在创建对象时分配。没有办法创建一个在初始化后只能分配一次的字段,例如在您的示例中。

编辑

注意readonly不是很强,不会导致两个具有相同字段的类型不兼容:

let fn  = Object.freeze({
    foo: "1"
}) // foo is readonly 
let nonReadonlyFn : { foo: string } =fn; // foo is not readonly but assignment is allowed
nonReadonlyFn.foo = "" // not a compiler error.

更新

如果您不知道密钥,您可以创建一个只读索引签名:

let fn: { 
    readonly [n: string] : string
} = { foo: "" };
fn["foo"] ="" // error
console.log(fn["foo"])

创建只读对象而不一次全部初始化它们的常用方法是拥有一个可变版本,对其进行变异,然后在完成将其分配给只读版本时:

let fnNotReadOnly: { 
    [n: string] : string
} ;
fnNotReadOnly["foo"] = "";
//When done mutating:
let fn : { 
    readonly [n: string] : string
} =  fnNotReadOnly;

fn["foo"] = ""
console.log(fn["foo"])

【讨论】:

  • 谢谢,我就是这么想的。如果属性是动态添加的呢?在这种情况下可以做些什么?
  • 只有在完成创建后将其分配给其他变量(该变量具有 readonly 字段)
  • 可能是只读索引签名?哪里所有的道具都是只读的?这适用于我的用例。我更新了 OP 以显示我的意思。
  • 我仍然不允许分配,只是只读访问,如果您不知道密钥,可能是您正在寻找的内容
  • 不要以为你会很幸运。很难跟踪该字段的第一次分配,尤其是在涉及控制流时。在创建时分配它仍然是最好的方法,或者有一个可变版本,然后将它分配给只读版本(在答案中添加了代码示例)
猜你喜欢
  • 1970-01-01
  • 2021-10-13
  • 1970-01-01
  • 2020-04-14
  • 1970-01-01
  • 2020-10-11
  • 2020-01-15
  • 2022-11-21
  • 1970-01-01
相关资源
最近更新 更多