ReasonML与TypeScript的比较

66

1
我认为这就像比较苹果和梨。你需要花些时间自己研究这些语言以及其他许多语言。仅仅看看权衡是无法获得对关键差异的深刻理解的。 - dardub
2
显然,ReasonML 是未来。我参加了几次会议,每个人都在谈论它,谈论它有多酷。我一定要学习它。有人正在使用 React 和 Reason(ReasonReact)开发应用程序,速度非常快。 - Patricio Vargas
1
如果您使用ReasonML,您将获得实际的保证类型,并可以开始使用像https://www.imandra.ai/这样的东西。如果您只想要看起来更像Java的JavaScript,则选择TypeScript。 - icc97
6个回答

70

现在有很多编程语言都可以用来编写 JavaScript。选择哪一种取决于您的需要和您熟悉的习惯

JavaScript 采用动态类型系统,而有些开发人员更喜欢静态类型系统。

  • TypeScript 或 Haxe 通过一个新的语言解决了这个问题,这个语言是静态类型的,并且只会被转译成 JavaScript。

  • Flow 是一个 JavaScript 预处理器,目的也是解决同样的问题,但无需学习一门新语言。如果你只需要一个类型系统,我建议采用这种方法。

一些 JS 开发者希望使用更多的函数式编程习惯(代数数据结构、不变性、模式匹配等)。许多编程语言都可以实现它(OCaml、Haskell、ReasonML、F#、Scala 等)。

  • ReasonML 是 OCaml 的一个语法糖,可以通过 BuckleScript 编译成本地或 JavaScript 代码。除了 ReasonML 语法接受 JSX 之外,所有可用于 Reason 的东西都可在 OCaml 中实现。ReasonML 可轻松针对 node.js 应用程序、react.js 应用程序或本地应用程序。

如果你来自 Java 或 C# 的世界,TypeScript 很容易学习。

如果您没有使用过 ML 语言(OCaml 或 F#)进行开发,则 ReasonML 学习难度较大。

我的建议:

  • 如果您只需要一个静态类型系统,请考虑 TypeScript

  • 如果您需要一个类型系统来开发 react.js 或 react-native 应用程序,请考虑 ReasonML,因为 ReasonReact 比 react.js 更好

  • 如果您需要一种编译成 js 的函数式编程语言,请考虑 ReasonML


9
不是很准确。动态类型意味着类型在运行时评估,而静态类型意味着类型在编译时评估。强类型和弱类型则更具争议性。我喜欢这个定义:https://youtu.be/UXBoiqRJ6DQ?t=5m6s - Thomas
@Thomas flow和TypeScript在本质上是相同的,为什么你认为TypeScript是“一门新语言”? - Tom Cumming
4
@TomCumming,两者都旨在输入JS,但Typescript是一种完整的语言,即使它是JS的超集,而Flow只是一个JavaScript预处理器。 为了运行TS代码,必须使用TypeScript编译器(用TypeScript编写)将其编译为JS。 使用Flow注释的JS应该由flow(用OCaml编写)进行预处理,但可以通过babel运行(或转换)而无需经过Flow的预处理。有关推理引擎的良好阅读材料:https://codeburst.io/inference-engines-5-examples-with-typescript-flow-and-reason-edef2f4cf2d3 - Thomas
@Thomas 你能否分享一下,你是否正在参与一个使用ReasonML开发生产项目的工作? - bernatfortet
1
@DominicWatson,你需要学习类型及其使用方法。这是它们存在的目的。 由于所有的JavaScript代码都应该是正确的TypeScript代码,因此不必学习TS语言即可使用带有TS的类型化JavaScript...但是TS具有特定的编程功能,如装饰器或环境模块声明。然而,随着像ReasonML、ELM或Nim等项目的成熟以及它们社区的增长,学习两者(flow和ts)的兴趣正在减少。 - Thomas
显示剩余6条评论

50

有很多取舍,其中许多取决于 ReasonML 在技术上只是 OCaml,因此继承了 OCaml 25 年的历史,成为一个本地编译语言,对 Web 上这个奇怪的 JavaScript 领域几乎没有考虑。

但是我认为最大的取舍在于 ReasonML 的稳健而灵活的类型系统和 TypeScript 能够轻松“潜入”现有 JavaScript 代码库中进行全面的静态检查能力之间。

TypeScript 的类型系统明确设计为不稳健,因此虽然它会在大多数情况下为您提供帮助,但无法给您许多保证。您真的不能完全信任该类型系统来支持您,这是具有适当的静态类型系统的最大优势之一。

TypeScript 还受到避免运行时类型信息的限制,这对于功能(例如模式匹配)至关重要,并且是使用 ReasonML 中类型数据的主要好处。

另一方面,ReasonML 要求明确定义其与现有 JavaScript 代码之间的边界。可以在某种程度上推断出类型,但仍必须在编译时确定。这使得 JavaScript 互操作更加费力,特别是如果随着现有 JavaScript 代码库的转换,边界逐渐移动。还不总是清楚如何对一些奇怪的东西进行类型化,但通常是可能的,希望只是暂时的,直到所有内容都被转换为 ReasonML 为止 :)

显然,我有偏见,但我希望这不会表现出明确选择一个赢家,至少因为真的没有。这是一个重大的权衡,至少在世界不完美的情况下。


你能否分享一下,你目前是否在进行使用 ReasonML 开发的生产项目? - bernatfortet
我目前有几个正在生产中的开源项目,比如:redexrebench。我目前正在使用 F# 和 Fable 进行开发,不过该项目距离可以投入生产还有很长的路要走。 - glennsl
@glennsl 如果你能简要评论一下你五年后对F#的经验,那将会很有趣。另外,你对Reason / ReScript有何经验? - undefined
1
嗨@Magne。由于工具问题和其他机会,我很快就放弃了F#。我认为它并没有得到很大的改进,相反,根据我听到的消息,由于微软的支持减少,情况可能恶化了。之后,我稍微接触了一下原生的Reason,过去几年一直在使用ReScript。Reason和ReScript之间的分离使得Reason在工具方面有了更好的发展,而ReScript在人机交互和平滑互操作方面有了更好的发展。其他方面,比如类型系统,基本上是相同的。 - undefined
另外,回答你几年前的问题 @bernatfortet,我目前正在一个拥有五万行 ReScript 代码的项目上工作。而且我曾经参与过 Onivim2 的开发,这是一个使用原生 ReasonML 的开源项目。你可以在这里查看:https://github.com/onivim/oni2 - undefined

22
在大型应用程序中,您需要许多功能,这些功能在ReasonML中默认提供:严格类型、如果您进行JSON编码/解码,则运行时验证、快速编译时间、不可变数据。
在TypeScript中,您将需要添加:
  1. ImmutableJS +其类型定义。
  2. json-schema+其类型定义的运行时验证器。然后您将必须在TypeScript中编写类型,并在json-schemas中定义模式。它们很快会失去同步。
  3. 一些疯狂的技巧来区分变量是特定类型(就像TS的官方文档中所述:https://www.typescriptlang.org/docs/handbook/advanced-types.html,“用户定义的类型保护”段落)。使用副作用(例如a.swim!== undefined)进行这些检查。在6个月内,此“if”语句将包含越来越多的检查。
  4. 如果您使用的包具有官方和维护的类型定义,则非常幸运。否则,您将得到自定义类型定义。
  5. 如果您在JS + TS中开发混合应用程序,则TS编译器无法创建可以在项目的其他部分导入的捆绑最终d.ts文件。您将不得不编写单独的d.ts文件,这些文件由工具(如dts-bundle)捆绑在一起。如果您所有内容都使用TS,则此问题不适用。
  6. 大型应用程序需要很长时间才能被TypeScript编译。
使用ReasonML:
  1. 不可变数据在语言中。
  2. 运行时验证器存在(bs-json默认具有)
  3. 模式匹配可使您避免这些疯狂的检查。
  4. 如果您想要使用的npm包具有BuckleScript绑定,则非常幸运。
  5. N/A。
  6. ReasonML编译非常快。

8
如果您想在TypeScript中实现不可变性,ImmutableJS并不是必需的。只需使用“readonly”属性修饰符和类型,如ReadonlyArray,ReadonlyMap,Readonly等。所有这些都包含在语言和其标准库中。 - iyegoroff
11
虽然“把它们放在语言中”和“将它们作为默认设置”之间存在很大的区别,但原因是不变的默认。 - Rotareti
3
您认为OP希望使用不可变数据。在我看来,使用TypeScript时,遵循面向对象编程会是更好的选择,因此当您需要状态管理时,像mobx或mobx-state-tree这样的工具会更加合适。但是,您可以通过使用本地的react.js API轻松解决它。当有多线程时,不可变性是一种胜利。在Web上,您可以使用OOP来处理应用程序的数据。另外,您是否有任何基准测试证实TS在大型应用程序中较慢?到目前为止,我在任何生产应用程序中都没有遇到过任何缓慢现象。 - Capaj
1
如果OP考虑使用ReasonML,那么不可变性很可能是他们追求的东西之一。大多数人可能通过React听说过Reason,鉴于React文档经常谈论不可变性的优势(例如Redux),再加上Facebook也开发了Immutable.js,因此OP对不可变性感兴趣似乎是合理的。 - icc97
2
对我来说,第六点应该排在首位。过去曾经参与Scala项目的开发,你会很快意识到备选方案的快速反馈循环的重要性。相比竞争对手,ReasonML的速度非常快。 - Wilfred Springer
显示剩余2条评论

19

注:

撇开所有实际方面不谈;

ML语言家族基于一个类型理论,称为System-F,例如Purescript和Haskell也使用该类型理论。

相比之下,Typescript缺乏这样一个成熟的基础,而是采用了一个带有许多特殊位的新型实验性类型系统(我甚至不确定它是否“形式化”)。

因此,从表面上看,TS的方法可能似乎很“实用”,但它引入了更多不必要的复杂性。System F只有很少的规则构成系统,而且非常通用,比TS的“理论”更容易推理。简单就是美。

此外,学习System-F所花费的努力是相当具有时间性的,并且可以转化为其他更强大的语言,比如Purescript。


10
它们非常不同。
- ReasonML是一种独立于JavaScript的语言,可以编译成JavaScript。 - TypeScript是JavaScript的严格超集,可以编译成JavaScript。
如果您想编写类型安全的代码,两者都是很好的选择。
- 如果您想编写类型安全的JavaScript,则应选择TypeScript。 - 如果您想编写类型安全的某种语言,并将其编译成JavaScript,则ReasonML是众多选项之一。在ReasonML的情况下,这种语言是OCAML。
更多信息:
我有偏见的观点:https://medium.com/@basarat/typescript-won-a4e0dfde4b08

2
你的回答和意见未提到Reason更像F#,具有不可变的联合类型。Reason与TypeScript完全不同,并计划成为React引擎的后续版本。目前,Facebook前端代码中有很多正在使用ReasonML进行重写。 - HMR

2

如果你注重函数式编程,那么Reason ML是一个很好的选择。而TypeScript也支持函数式编程,并且有着活跃的社区支持。几乎所有热门库都有TypeScript的类型定义文件。我个人更喜欢使用fpts(https://github.com/gcanti/fp-ts/blob/master/README.md)。它在TypeScript中提供了函数式编程的优点,并包括运行时检查。虽然在ts中缺少类型构造器,但如果您可以接受这一点,那么选择TypeScript也是不错的。


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