为什么打字稿允许 referencing/assigning 只读 type/property 可变类型?

Why typescript allows referencing/assigning a readonly type/property by mutable type?

为什么打字稿不强制只读关键字并阻止我们将只读 属性 传递给非只读关键字,这违背了要点

let foo: {
    readonly bar: number;
} = {
        bar: 123
    };

function iMutateFoo(foo: { bar: number }) {
    foo.bar = 456;
}

iMutateFoo(foo); // The foo argument is aliased by the foo parameter
console.log(foo.bar); // 456!```

readonly关键字只是一个ts-compiler检查。话虽如此,您是在告诉编译器 mutate 函数接受一个 non-readonly 参数。

然而,如果你真的输入正确,编译器会报错,例如

type test = { readonly bar: number };

let foo: test = {
    bar: 123
};

function iMutateFoo(foo: test) {
    foo.bar = 456; // error
}

这是一个 known behavior whose surprising effects inspired an issue originally titled "readonly modifiers are a joke"。问题的简短答案是 "it would have broken backwards compatibility when readonly was introduced"。长答案来自以下评论:

@ahelsberg said:

In order to ensure backwards compatibility, the readonly modifier doesn't affect subtype and assignability type relationships of the containing type (but of course it affects assignments to individual properties).

Consider the following code:

interface ArrayLike<T> {
  length: number;
  [index: number]: T;
}

function foo(array: ArrayLike<string>) {
    // Doesn't mutate array
}

var s = "hello";
var a = ["one", "two", "three"];
foo(s);  // s has readonly length and index signature
foo(a);

In existing TypeScript code there is no way to indicate if a particular property is intended to be read-only or mutable. In the code above, foo doesn't mutate the array it is passed, but there is nothing in the code that says it can't. However, now that we've added a readonly modifier to the length property and the index signature in the String interface (because they really are read-only), the foo(s) call above would be an error if we said that a readonly property is incompatible with a property without readonly. Specifically, we can't interpret the absence of a readonly modifier to mean read-write, we can only say that we don't know. So, if an interface differs from another interface only in the readonly modifiers on its properties, we have to say that the two interfaces are compatible. Anything else would be a massive breaking change.

好了。如果你想表达你对解决这个问题的支持,你可能想转到那个 GitHub issue 并给它一个或描述你的用例(如果它引人注目且尚未提及)。

总之,希望对您有所帮助;祝你好运!