Types are the highlight of ReScript! They are:
numbervariable might change into a
stringsometimes. This is an anti-feature; it makes the code much harder to understand when reading or debugging.
Static. ReScript types are erased after compilation and don't exist at runtime. Never worry about your types dragging down performance. You don't need type info during runtime; we report all the information (especially all the type errors) during compile time. Catch the bugs earlier!
Fast. Many developers underestimate how much of their project's build time goes into type checking. Our type checker is one of the fastest around.
Inferred. You don't have to write down the types! ReScript can deduce them from their values. Yes, it might seem magical that we can deduce all of your program's types, without incorrectness, without your manual annotation, and do so quickly. Welcome to ReScript =).
The following sections explore more of our type system.
This let-binding doesn't contain any written type:
ReScript knows that
score is an
int, judging by the value
10. This is called inference. Likewise, it also knows that the
add function takes 2
ints and returns an
int, judging from the
+ operator, which works on ints.
But you can also optionally write down the type, aka annotate your value:
If the type annotation for
score doesn't correspond to our inferred type for it, we'll show you an error during compilation time. We won't silently assume your type annotation is correct, unlike many other languages.
You can also wrap any expression in parentheses and annotate it:
Note: in the last line,
(~radius as r: int) is a labeled argument. More on this in the function page.
You can refer to a type by a different name. They'll be equivalent:
Types can accept parameters, akin to generics in other languages. The parameters' names need to start with
The use-case of a parameterized type is to kill duplications. Before:
Note that the above codes are just contrived examples for illustration purposes. Since the types are inferred, you could have just written:
The type system infers that it's a
(int, int, int). Nothing else needed to be written down.
Type arguments appear in many places. Our
array<'a> type is such a type that requires a type parameter.
If types didn't accept parameters, the standard library would need to define the types
arrayOfTuplesOfInt, etc. That'd be tedious.
Types can receive many arguments, and be composable.
Just like a function, a type can reference itself within itself using
Types can also be mutually recursive through
ReScript's type system is robust and does not allow dangerous, unsafe stuff like implicit type casting, randomly guessing a value's type, etc. However, out of pragmatism, we expose a single escape hatch for you to "lie" to the type system:
This declaration converts a
myType1 of your choice to
myType2 of your choice. You can use it like so:
Obviously, do not abuse this feature. Use it tastefully when you're working with existing, overly dynamic JS code, for example.
More on externals here.
Note: this particular
external is the only one that isn't preceded by a