Может ли `readonly` TypeScript полностью заменить Immutable.js? - PullRequest
5 голосов
/ 29 апреля 2019

Я работал над несколькими проектами, используя React.js. Некоторые из них использовали Flux, некоторые Redux, а некоторые были просто приложениями React, использующими Context.

Мне очень нравится, как Redux использует функциональные шаблоны. Однако есть большая вероятность, что разработчики непреднамеренно изменят состояние. При поиске решения, в основном, есть только один ответ - Immutable.js. Если честно, я ненавижу эту библиотеку. Это полностью меняет способ использования JavaScript. Более того, это должно быть реализовано во всем приложении, в противном случае вы получите странные ошибки, когда некоторые объекты являются простыми JS, а некоторые - неизменяемыми структурами. Или вы начинаете использовать .toJS(), что, опять же, очень и очень плохо.

Недавно мой коллега предложил использовать TypeScript. Помимо безопасности типов, у нее есть одна интересная особенность - вы можете определять свои собственные структуры данных, у которых все их поля помечены как readonly. Такая структура была бы по существу неизменной.

Я не эксперт ни по Immutable.js, ни по TypeScript. Однако обещание иметь неизменные структуры данных внутри хранилища Redux и без использования Immutable.js кажется слишком хорошим, чтобы быть правдой. Является ли TypeScript readonly подходящей заменой для Immutable.js? Или есть какие-то скрытые проблемы?

Ответы [ 3 ]

3 голосов
/ 29 апреля 2019

Хотя верно, что модификатор readonly TypeScript существует только в типе разработки и не влияет на код времени выполнения, это верно для всей системы типов. То есть ничто не мешает вам во время выполнения присвоить число переменной типа string. Таким образом, этот ответ - своего рода красная сельдь ... если во время разработки вас предупреждают, что вы пытаетесь изменить что-то, помеченное как const или readonly, то это, возможно, устранит необходимость в расширенной проверке во время выполнения.

Но есть главная причина, по которой readonly недостаточно. Существует нерешенная проблема с readonly, которая заключается в том, что в настоящее время (по состоянию на TS3.4) типы, которые отличаются только своими атрибутами readonly, взаимно назначаются. Который позволяет вам легко прорваться сквозь защитную оболочку readonly любого имущества и связываться с внутренностями:

type Person = { name: string, age: number }
type ReadonlyPerson = Readonly<Person>;

const readonlyPerson: ReadonlyPerson = { name: "Peter Pan", age: 12 };
readonlyPerson.age = 40; // error, "I won't grow up!"

const writablePerson: Person = readonlyPerson; // no error?!?!
writablePerson.age = 40; // no error!  Get a job, Peter.

console.log(readonlyPerson.age); // 40

Это очень плохо для readonly. До тех пор, пока это не будет решено, вы, возможно, согласитесь с подателем предыдущего выпуска, который первоначально назвал проблему «модификаторы только для чтения - шутка» ?.

Даже если это разрешится, readonly может не охватывать все варианты использования. Вам также необходимо пройти через все интерфейсы и типы в ваших библиотеках (или даже в стандартных библиотеках) и удалить методы, изменяющие состояние. Таким образом, все варианты использования Array должны быть изменены на ReadonlyArray, а все варианты использования Map должны быть изменены на ReadonlyMap и т. Д. После того, как вы это сделаете, у вас будет довольно безопасный способ представления неизменности , Но это много работы.

В любом случае, надеюсь, это поможет; удачи!

1 голос
/ 29 апреля 2019

Цель Immutable.js не состоит в том, чтобы не дать разработчику сделать незаконную мутацию во время компиляции.Он предоставляет удобный API для создания копий объекта с некоторыми измененными его свойствами.Тот факт, что вы получаете безопасность типов на объектах, которыми вы управляете с помощью immutable.js, является просто побочным эффектом от его использования.

Typescript - это «просто» система ввода.Он не реализует никаких функций Immutable.js, позволяющих делать копии неизменяемых объектов.Все, что он делает, объявляя переменную как readonly, это проверяет во время компиляции, что вы не изменили ее.То, как вы разрабатываете свой код для обработки неизменяемости, не входит в сферу системы ввода, и вам все равно нужен способ борьбы с ним.

React обеспечивает неизменность, предоставляя метод setState вместо изменения объекта состояниянепосредственно.Он заботится о слиянии измененных свойств для вас.Но если вы, например, используете redux, вам может понадобиться удобное решение для обработки неизменности.Это то, что Immutable.js предоставляет, и машинопись никогда не будет, и это не зависит от того, нравится ли вам API или нет.

1 голос
/ 29 апреля 2019

Есть две проблемы с этим:

1) Вы должны использовать readonly и / или что-то вроде ReadonlyArray до конца, что подвержено ошибкам.

2) readonly существует исключительно во время компиляции, а не во время выполнения, если не поддерживается неизменными хранилищами данных. Как только ваш код передан в JS, ваш код runtime может делать все, что захочет.

...