#typescript #readonly
Вопрос:
Почему typescript не применяет ключевое слово только для чтения и не запрещает нам передавать свойство только для чтения в свойство, не предназначенное только для чтения, это противоречит сути
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!```
Комментарии:
1. Я написал правило ESLint, чтобы предотвратить этот сценарий: github.com/danielnixon/…
Ответ №1:
Это известное поведение, удивительные эффекты которого вдохновили проблему, первоначально озаглавленную «модификаторы только для чтения-это шутка». Короткий ответ на вопрос: «это нарушило бы обратную совместимость, когда readonly
было введено». Длинный ответ следует из следующего комментария:
@ahelsberg сказал:
Для обеспечения обратной совместимости
readonly
модификатор не влияет на отношения подтипов и типов назначаемости содержащего типа (но, конечно, он влияет на назначения отдельным свойствам).Рассмотрим следующий код:
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);
В существующем коде машинописного текста нет способа указать, предназначено ли конкретное свойство только для чтения или изменяемо. В приведенном выше коде
foo
массив, который он передается, не мутирует, но в коде нет ничего, что говорит, что это невозможно. Однако теперь, когда мы добавилиreadonly
модификатор вlength
свойство и подпись индекса вString
интерфейсе (поскольку они действительно доступны только для чтения),foo(s)
приведенный выше вызов был бы ошибкой, если бы мы сказали, чтоreadonly
свойство несовместимо со свойством безreadonly
. В частности, мы не можем интерпретировать отсутствиеreadonly
модификатор, означающий чтение-запись, мы можем только сказать, что мы не знаем. Итак, если интерфейс отличается от другого интерфейса толькоreadonly
модификаторами его свойств, мы должны сказать, что эти два интерфейса совместимы. Все остальное было бы огромным прорывным изменением.
Так что вот оно что. Если вы хотите продемонстрировать свою поддержку в решении этой проблемы, вы можете перейти к этой проблеме на GitHub и дать ей 👍 или описать свой вариант использования, если он убедителен и еще не упомянут.
В любом случае, надеюсь, это поможет; удачи!
Ответ №2:
readonly
Ключевое слово-это только проверка компилятора ts. Сказав это, вы сообщаете компилятору, что функция mutate принимает параметр, не предназначенный только для чтения.
Однако, если вы на самом деле введете его правильно, компилятор будет жаловаться, например
type test = { readonly bar: number };
let foo: test = {
bar: 123
};
function iMutateFoo(foo: test) {
foo.bar = 456; // error
}
Комментарии:
1. я хочу сказать, что вы не можете гарантировать неизменность ниже по потоку, хотя они могли бы обеспечить проверку времени компиляции только для чтения в рамках проверки информации о типе, и я спрашиваю, почему они этого не сделали