TypeScript只读修饰符被别名去除

3

显然,TypeScript允许您通过简单的赋值来从类型中删除readonly修饰符,像这样:

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";
}

我觉得这样做会使得意外修改只读字段变得非常容易,或者我漏掉了什么?我是否错误地使用了readonly?在typescript中是否有更严格的替代方案来禁止这种行为?

编辑:由于确实是这样工作的,这里有一个解决方法,虽然它并不完美,但在我的特殊情况下似乎有所帮助:

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";
}

一个有趣的解决方法,如果你不介意额外的步骤和必须明确使用它的事实的话 :) - Titian Cernicova-Dragomir
1
我的意思是,我确实介意,只是没有更好的选择:D。 - michalburger1
1个回答

2

这是一个已知问题,在此处有文档记录。问题的要点在于readonly修饰符不影响可分配性。这确实限制了readonly修饰符的使用价值。

目前没有已知的方法可以使其更加严格,没有编译器选项,也没有聪明的类型技巧可以做到这一点。我对这个声明非常有信心,因为在类型系统中无法区分类型上是否存在readonly(无论是在条件类型还是映射类型中)。没有这种能力,我们就无法引入错误来防止赋值。

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


谢谢Titian!告诉我你对我的解决方法有什么看法。 - michalburger1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接