使用 TypeScript 为对象定义 constant/ro 属性

Defining constant/ro properties on objects with TypeScript

使用 TypeScript,有什么方法可以强制不重新分配?

假设我有这个:

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

有没有办法在第二行得到一个编译错误?一旦我分配了 foo 属性,我想它应该是 ReadOnly

我的案例 foo 可以遵守此接口:

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

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

如果你使用 class 你可以将字段本身标记为 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"])