- Full-fledged support for pattern-matching exhaustiveness check, not something you have to bake together using a 'tag' field. This means if you match on i.e. integers, the compiler will warn you if you don't include a catch-all default case.
- Simple module system where you don't need to deal with named vs default imports and all the weird bugs getting them mixed up can bring
- TypeScript's inherent JS-like nature can pop up subtle bugs like forgetting to type a pair of parentheses:
function isSupported(): boolean {
return false;
}
function test() {
console.log(true && isSupported); // true
}
Or doing object/array indexing and forgetting to handle the case of 'undefined' because TypeScript doesn't enforce that. Or how any typings from before version 2 are suspect because they were written with the assumption that every type can be implicitly nullable. There are lots of these little footguns all over the place.
- Higher-quality bindings: more stuff captured at the type level, you're not left to deal with bindings full of 'any', 'object', and 'function'
It's not even just about safety though. One of the biggest productivity drivers in Reason is its iteration speed–the compiler is so fast that you can try out changes basically as fast as you can save the file. And there are other things, like how all modules are implicitly available in scope, so you don't need to manage a 'wall of imports' at the top of every file before you can actually get to the code itself.