类型
类型是 ReScript 的亮点!它们是:
强类型。一个类型无法变为另一个类型。在 JavaScript 中,当代码执行时(也称运行时),变量的类型可能会改变。例如,一个类型为
number
的变量可能变为string
类型。这是不好的特性,它使代码在阅读或调试时更难理解静态类型。ReScript 类型在编译后被擦除,在运行时不存在。不必担心类型会拖累性能。你在运行时不需要类型信息;我们在编译时报告所有信息(尤其是所有类型错误)。更早地捕获错误!
健全(sound)。这是我们与其他编译到 JavaScript 的带类型语言的最大区别。我们的类型系统保证永远不会出错。大多数类型系统对一个值的类型进行猜测,有时在编辑器中不能显示正确的类型。我们不这样做。我们相信,由于与期望不匹配,一个会出错的类型系统最终会变得危险
快速。许多开发者低估了项目构建时类型检查的耗时。我们的类型检查器是最快的之一
类型推导。你不必写出类型!ReScript 可以从值中推导出类型。是的,我们可以推断出你的程序的所有类型,没有不正确的地方,不需要你手动标注,而且速度很快,看起来就像魔法一样。欢迎来到 ReScript =)
下面的章节将探讨类型系统的更多内容。
类型推导
这个 let 绑定不包含任何手写的类型:
ReScript 知道 socre
是一个 int
,通过 10
来判断。这就是所谓的推导。同样,它也知道 add
函数接受两个 int
并返回了一个 int
,这是由对 int
做加法的 +
运算符判断的。
类型标注
但你也可以选择性地写下类型,也就是标注你的值:
如果 score
的类型标注与我们推断的类型不一致,我们会在编译时向你显示一个错误。我们不会默默地假定你的类型标注是对的,这与许多其他语言不同。
你也可以用括号把任何表达式包起来,并对其进行标注:
注意:在最后一行,(~radius as r: int)
是一个标签参数。查看 函数 章节以了解更多。
类型别名
你可以用不同的名字指代一个类型。它们是等价的:
类型参数(泛型)
类型可以接受参数,类似于其他语言中的泛型。参数名必须以 '
开头。
参数化类型的应用是为了消除重复代码。使用前:
使用后:
注意,上述代码只是为了说明问题而设计的例子。因为类型是推断出来的,你可以直接写:
类型系统推断出它是一个 (int, int, int)
,什么都不需要写。
类型参数出现在很多地方。 array<'a>
类型就是这样一种类型,它需要一个类型参数:
如果类型不能接受参数,标准库将需要定义 arrayOfString
,arrayOfInt
,arrayOfTuplesOfInt
等类型。这将是很啰嗦的。
类型可以接收许多参数,并且是可组合的。
递归类型
就像函数一样,一个类型也可以使用 rec
在其内部引用自己:
互递归类型
类型也可以通过 and
来实现 相互 递归:
类型逃生通道
ReScript 的类型系统非常健壮,不允许出现危险、不安全的情况,如隐式类型转换,随机猜测值的类型等。然而,出于实用主义的考虑,我们为你提供了一个单一的逃生通道,以便你向类型系统“撒谎”:
这个声明将你选择的 myType1
转换为你选择的 myType2
。你可以像这样使用它:
很明显,不要滥用这个特性。当你在处理现有的,过于动态的 JS 代码时,要有品位地使用它。
关于 external 的更多信息请参考 这里。
注意: 上面代码中这个特别的 external
是唯一一个前面没有 @
属性的。