打字稿只读修饰符被别名剥离

时间:2018-09-17 11:48:57

标签: typescript

显然,打字稿允许您通过如下简单的赋值从类型中删除只读修饰符:

function foo(x: { readonly value: string }) {
    x.value = "new value"; // This would fail, as it should
    bar(x); // But this is okay?
}

function bar(x: { value: string }) {
    x.value = "new value";
}

在我看来,这将使偶然更改只读字段变得非常容易,还是我错过了什么?我是否使用了只读错误?打字稿中是否有任何更严格的替代方法可以禁止这种行为?

编辑:由于这确实是它的工作方式,因此以下变通方法似乎对我的特定情况有所帮助,尽管这绝不是完美的解决方案:

type ConstAware<T> = { __writable: true } & { [P in keyof T]: T[P] };
type Const<T> = T extends ConstAware<any> ? { readonly [P in Exclude<keyof T, "__writable">]: T[P] } : never;

type Foo = ConstAware<{
    value: string;
}>;

function foo(x: Const<Foo>) {
    let y: Foo = x; // Not allowed, yay
    y.value = "new value";
}

1 个答案:

答案 0 :(得分:1)

这是一个已知问题,已记录here。其要点是readonly修饰符不会影响可分配性。不幸的是,这确实限制了readonly修饰符的用途。

没有已知的方法可以使此更为严格,没有编译器选项,也没有巧妙的类型技巧来做到这一点。我对此声明非常有信心,因为无法辨别类型(条件或映射类型)上存在readonly的类型系统。没有此功能,我们将无法真正引入不允许分配的错误。

注意这是在Typescript 3.1是当前版本时编写的,TypeScript的未来版本(希望如此)可能证明我错了。