【问题标题】:Typescript dictionary with readonly keys带有只读键的打字稿字典
【发布时间】:2017-06-16 15:37:42
【问题描述】:

是否可以在 typescript 中使用只读键声明字典类?

代码:

class Dictionary {
    readonly[key: string]: string;

    constructor(props: Dictionary) {
        for (const key in props) {
            this[key] = props[key];
        }
    }
}

通常在构造函数中允许设置只读属性的值,但这里编译器抱怨“'Dictionary'类型的索引签名只允许读取'。

【问题讨论】:

  • 我们也应该用截图来回答吗?
  • 如果您想为有效答案添加屏幕截图,我将不胜感激,但我仅添加屏幕截图以显示打字稿编译器抱怨的地方。我会将代码添加为文本,好吧太晚了;)谢谢 Nitzan

标签: dictionary typescript readonly


【解决方案1】:

我不确定这是否是设计使然,the docs 对此感到困惑:

现在可以使用 readonly 声明属性或索引签名 修饰符被认为是只读的。

但是:

只读属性可能有初始化器并且可以分配给 同一类声明中的构造函数,但除此之外 不允许分配给只读属性

因此,虽然属性和索引签名都可以是只读的,但也许只能在构造函数中分配属性。
不太清楚,你可以打开一个 issue 找出来。

但是,您可以使用Object.assign,这不会导致编译错误,并且还会清除代码:

class Dictionary {
    readonly[key: string]: string;

    constructor(props: Dictionary) {
        Object.assign(this, props);
    }
}

let d1 = new Dictionary({ key1: "one", key2: "two" });
console.log(d1); // Dictionary {key1: "one", key2: "two"}

let d2 = new Dictionary(d1);
console.log(d1); // Dictionary {key1: "one", key2: "two"}

(code in playground)


编辑

使用 Object.assign 比你的 for/in 循环更好,下面是一个例子:

class A {
    [key: string]: any;

    constructor() {
        this["k1"] = "v1";
        this["k2"] = "v2";
    }

    method() {}
}

let a = new A();
let a1 = Object.assign({}, a);
console.log(a1); // { k1: "v1", k2: "v2" }

let a2 = {};
for (const key in a) {
    a2[key] = a[key];
}
console.log(a2); // { k1: "v1", k2: "v2", method: () }

(code in playground)

如您所见,使用 for/in 循环还会遍历原型属性,这可能不是您想要的。
Object.assign 没有这个问题。

另一种选择是使用Object.keys

let a3 = {};
Object.keys(a).forEach(key => a3[key] = a[key]);
console.log(a3); // { k1: "v1", k2: "v2" }

【讨论】:

  • ok Object.assign 现在听起来像是一个有效的解决方案,但我尽量避免使用它,因为正如您在此处看到的那样,它只是覆盖了 readonly 标志。我会按照你的建议打开一个问题
  • 问题已经存在,欢迎参与讨论github.com/Microsoft/TypeScript/issues/6781
  • 但是如果构造函数允许你赋值,那么它也会“覆盖只读标志”。检查我修改后的答案。
  • 这只是加强了我的感觉,它确实是 typescript 编译器规范的问题。当然 object assign 也会遍历对象键,但是当在构造函数中调用 Object.assign 时,它应该会出现相同的编译器错误。
  • 使用 Object.setProperty 并在设置时以这种方式将它们设为只读 - 实际上就像使用 get 关键字而不是 readonly (但必须在 init 时给定一个值,只是以防任何阅读此内容的人试图使其工作)。请记住,readonly 只是一个提示,实际上并没有以任何方式强制执行...
猜你喜欢
  • 1970-01-01
  • 2020-07-03
  • 1970-01-01
  • 2019-07-09
  • 1970-01-01
  • 2017-03-24
  • 2019-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多