TypeScript的`readonly`可以完全替代Immutable.js吗?

Sto*_*orm 7 typescript reactjs immutable.js redux

我已经使用React.js进行了几个项目。他们中的一些人使用了Flux,一些人使用Redux,还有一些只是使用Context的普通React应用程序。

我非常喜欢Redux使用功能模式的方式。但是,开发人员很可能无意间改变了状态。在寻找解决方案时,基本上只有一个答案-Immutable.js。老实说,我讨厌这个图书馆。它完全改变了您使用JavaScript的方式。而且,它必须在整个应用程序中实现,否则当某些对象是纯JS而某些对象是不可变结构时,您最终会遇到奇怪的错误。或者您开始​​使用.toJS(),这又是-非常非常糟糕。

最近,我的一位同事建议使用TypeScript。除了类型安全之外,它还有一个有趣的功能-您可以定义自己的数据结构,其所有字段都标记为readonly。这样的结构本质上是不可变的。

我不是Immutable.js或TypeScript的专家。但是,在Redux存储区中拥有不可变数据结构而无需使用Immutable.js的承诺似乎太过真实了。TypeScript是否readonly可以替代Immutable.js?还是有隐藏的问题?

jca*_*alz 8

虽然 TypeScript 的修饰符确实readonly只存在于设计类型中,不会影响运行时代码,但对于整个类型系统来说也是如此。也就是说,没有什么可以阻止您在运行时将数字分配给 类型的变量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
Run Code Online (Sandbox Code Playgroud)

这对 来说非常糟糕readonly。在这个问题得到解决之前,您可能会发现自己同意之前的问题提交者的观点,他最初将该问题命名为“只读修饰符是个笑话”。

即使这个问题得到解决,也readonly可能无法涵盖所有​​用例。您还需要遍历库(甚至标准库)中的所有接口和类型,并删除改变状态的方法。因此, 的所有使用Array都需要更改为ReadonlyArray, 的所有使用Map都需要更改为ReadonlyMap,等等。一旦你这样做了,你就会有一个相当类型安全的方式来表示不变性。但这是一项繁重的工作。

无论如何,希望有帮助;祝你好运!


tri*_*ixn 5

目的Immutable.js不是阻止开发人员在编译时进行非法变更。它提供了一个方便的 API 来创建对象的副本,并更改​​其某些属性。事实上,使用 immutable.js 管理的对象可以获得类型安全性,这基本上只是使用它的副作用。

Typescript“只是”一个打字系统。Immutable.js它没有实现任何复制不可变对象的功能。当将变量声明为 时readonly,它所做的就是在编译时检查您没有改变它。如何设计代码来处理不变性不是类型系统的范围,您仍然需要一种处理它的方法。

React 通过提供方法setState而不是直接改变状态对象来确保不变性。它负责为您合并更改的属性。但是,如果您使用 redux,您可能也需要一个方便的解决方案来处理不变性。这是Immutable.jstypescript 永远不会提供的,它与你是否喜欢 api 无关。

  • 我明白你在说什么。我只是无法想象如果您的代码库是“无突变”的,会发生运行时突变的情况。 (2认同)
  • @Storm 但这也不是 immutable.js 的工作来确保而不是使用打字稿。事实上,您可以同时使用两者。Immuable.js 帮助您处理在运行时必须不可变的对象的修改。如果您不使用它,您仍然必须提供自己的实现来处理该问题。 (2认同)