Long term goals vis-à-vis TypeScript?

Let me add some context before I ask the questions I have.

A while back, I played around with Reason for several months and almost picked it for one of my earlier projects but for a few reasons, went ahead with TypeScript. After that, I didn’t keep up with the events in the Reason community and so was quite surprised when I read about the syntax changes and about ReScript in general. I’ve spent the past few days trying to catch up and get up to speed with the facts and changes. Thankfully, for my case, the new setup seems just as fine.

I’m an independent, self-employed full stack developer who builds products and maintains a lot of web apps. I’ve been a highly satisfied and productive TypeScript user for several years now. TypeScript was a big improvement over vanilla JavaScript, reduced cognitive load, made maintenance a lot easier and has a big ecosystem of tools and learning resources.

If typescript had a sound type system and pattern matching, I likely wouldn’t be here. But it doesn’t and it will likely never. Hence my continued interest in languages like F# (via fable), PureScript, Reason (and now ReScript). A few reasons for my interest are:

  • domain modeling is much easier in these languages
  • these languages are more expressive and less verbose (important when reading through old-ish code bases and adding new features and/or fixing bugs)
  • a sound type system means one less thing for me to worry about

The reason why ReScript appeals to me over the other options is mainly because of the interop story, via GenType, with TypeScript. I could, in theory, create the core of the apps in ReScript and use TypeScript at the edges in cases where ReScript falls short (with libs like TypeORM or bindings for third party libs like blueprintjs, for example).

However, it only makes sense to go down this road if at some point in the future, I can completely replace TypeScript with ReScript. Otherwise the cost of splitting the code base into two languages (potentially three for cases where I use Go for the backend) will outweigh the benefits in my case.

With this context, here are my questions:

  • Is it a core goal of the ReScript team to become a direct alternative to TypeScript in both the frontend (browser) and the backend (via node.js, not OCaml)?
  • Is maintaining a good interop story with Flow/TypeScript a core goal of the ReScript team?
  • If I were to start a new project today, should I start with the 8.0 syntax or the 8.2 syntax?

I’m not too concerned about the timeline as long as these things are part of the long term plan.

7 Likes

Hey @kul,

First of all, we described the difference between ReScript & TypeScript in our documentation here.

Our longterm goal is to be a proper alternative to write typed JS without too many compromises on the soundness, expressiveness and interop capabilities (while having a nice looking and simple syntax). Since we are targeting JS as our compile target, we aim for the Frontend and NodeJS space (and anything else running on JS really!)… so I guess it’s safe to say that we are trying to be a type safer alternative to TypeScript (each with their own up and downsides of course).

Native compilation, like Reason Native / OCaml does, is a non goal right now. An excerpt from our FAQ:

Our focus is a solid JS story right now. In the future, if there’s strong demand, we might consider it.


GenType is part of the ReScript core infrastructure, has constantly improved in the past two years and will continue to be supported in the long term. Flow compatibility is relevant for legacy codebase support, and TypeScript interop will be an important feature for us as well.


We are working hard on the VSCode plugin to add support for the most important features, such as error diagnostics for syntax / type errors (should be ready by now in VSCode), type hints and autocompletion. If you don’t mind working without autocompletion / type hints, feel free to run with the ReScript syntax already.

Otherwise go with the Reason v3.6 syntax for now (which is also supported by rescript > 8.2), and later on use the bsc -format myfile.re > myfile.res to automatically upgrade to the newer ReScript syntax as soon as you feel comfortable doing so.

It’s probably fair to mention that starting out with Reason v3.6 is only a way to get the ball rolling. If you want to commit on the ReScript platform, you should really consider upgrading to ReScript syntax later on, since we will be exclusively focusing on ReScript syntax in the future (e.g. our newest docs changes will all be written with ReScript syntax in mind).


Hope this answers your questions!

4 Likes

Hey @ryyppy,

Thank you very much for the response. It does address all of my questions very well indeed.

I’m now seriously considering including ReScript in my stack and will be creating a full stack TypeScript + ReScript proof of concept for myself over the weekend to make the decision. I’m no masochist but I’ll likely start with the latest ReScript syntax (mainly to avoid accidentally using features from Reason that have been removed in ReScript)

1 Like

Hi, are you interested in native-compiled Reason for the backend? Or planning to stick with Go?

Depending on the use case, I’ll stick with either Go or TypeScript/ReScript with node.js.

This is just out of familiarity and the fact that these languages have huge ecosystems that make development extremely productive. That said, if native compiled Reason can provide a roughly comparable experience, I’d be tempted to switch but only if there would also be high reuse of code across the backend and the frontend.

For a ReScript/Reason/OCaml stack you may be able to achieve a nice amount of code reuse in the domain types and business logic, but probably not elsewhere (i.e. UI code or service layer code/networking). I have an example of shared types if you’re interested: https://github.com/yawaramin/fullstack-reason/

2 Likes

Domain types, business logic and validation are the only parts that I’d share code for anyway so this sounds quite compelling. Checking out your repo now. Thank you so much for sharing (and creating it, of course!)

1 Like

@yawaramin The repo looks really helpful!

Do you see the repo being just as relevant/useful going forward given that ReScript and Reason could potentially (likely?) diverge?

Thank you, glad it helps. I believe it may be helpful for some folks going forward, as long as they are prepared to deal with some subtle syntactic differences (and type) differences. In the near future, Reason syntax will look more like ReScript, so they will be pretty close:

  • Reason type parameters will also use <...> instead of (...) like now
  • Reason will also use backticks for multiline strings (as far as I remember)

The subtle differences will be that Reason will continue to use [] for lists and [||] for arrays, and that Reason types will continue to be recursive by default (this can be changed though), while ReScript types will be non-recursive (this can’t be changed).

For some people, I know it will be annoying to overcome these differences; for others, they won’t care too much. Depends on other factors.

Based on that, it seems that if ReScript were to be a candidate for full stack dev, it would have to be via node.js and not native Reason/OCaml

Right, Node.js is the best (and only) way to do fullstack ReScript. For the purposes of this discussion I’m ignoring niche JavaScript engines that may exist in other VMs, e.g. Rhino.

Hello @kul =)

For full-stack, we don’t recommend sharing code with native. The ROI currently isn’t there yet and you’d be going through only unofficial workflows (though ReScript -> Nodejs is definitely proven and recommended). The sharing of data types is ideally temporarily anyway, before a dedicated schema language with versioning and migration is introduced and obsolete many use-cases of said sharing.

In addition to what @ryyppy said, regarding your questions:

  • domain modeling is much easier in these languages
  • these languages are more expressive and less verbose

A common misconception (sometime accidentally perpetrated by a tiny part of our community) is that we’re optimizing for domain modeling and expressivity. In reality, we’re not; we don’t try to be under-expressive but we also don’t try to be over-expressive and invent features that give you the tightest modeling of your domain (which is hardly a useful goal usually). Technically speaking, it’s possible that TypeScript is a superset of ReScript in terms of features (plus a giant bunch of oddities), so you’ll likely model your domain tighter in TS. But we all know where this ends up:

  • The last 5% of a tight modeling often ends up costing a disproportional amount of the readability and maintenance.
  • Too many fancy type tricks is all-around a negative, though it affects you less if you’re solo and don’t share your libraries too much.
  • And yes, it’s much harder to provide soundness and compilation perf when things get complex.

What ReScript offers is a subset of tried and true features that model your domain well enough without letting you shoot yourself in the foot by going overboard with contemporary FP. Most of our competitions aren’t geared toward designing those constraints, the lack of which leaves an overly large solution space and makes it much harder to hit an efficient solution.

Concretely speaking, what you’d want likely isn’t a 100 ways, but a few proven ways, to model your domain. So while it’s unlikely that you’ll transcribe your TS code straight to ReScript, a few extra tweaks here and there will get you there.

(We do try to model tightly when it comes to JS interop, but that’s mainly due to our goal of having as much cost-free interop as possible. Necessary complexity.)

1 Like

Hey @chenglou,

Thank you very much for sharing your thoughts on my questions. This was very helpful.

That ReScript on the server will have to be via Nodejs was my initial understanding as well. For a brief moment during the above conversation I thought I might have missed something but by the end of it it became clear again. I haven’t used the native Reason/OCaml stack so it’s not an issue for me at all.

I understand what you’re saying and in my opinion it’s a positive thing.

I’m reasonably satisfied with TypeScript but one of the issues with it is that 10 teams using TypeScript will have 10 different programming styles. That means that while it technically is just one language, in practice it doesn’t feel like it across different code bases. Working mostly alone as I do, programming styles across teams isn’t a problem for me but I do run into the same issue across my own projects over a period of time.

This in stark contrast to the codebases I have in Go where I can open something I wrote 5 years ago and just get on with it right away (well, after quickly porting those over to Go modules anyway). ReScript feels like it could be something like Go has been for me in terms of long term maintainability and simplicity but with a better type system. To this end, I appreciate the language being kept small and focused. In terms of the type system, the existing feature set gives me most of what I’d need.

A well curated subset with a few goodies (like pattern matching, piping, etc.) is exactly what I’ve been looking for and ReScript might fit the bill. And GenType gives ReScript a big advantage over other comparable languages available because it reduces the risk and cost of using ReScript substantially.

I won’t be changing my existing applications over to use ReScript as the effort wouldn’t justify the cost so there won’t be any rewrite/port. If I do start using it, it’ll be in new projects/apps.

The only concern I had was about the long term goals of the ReScript team and project. These have been addressed and what remains is for me to test out ReScript + TypeScript in a small proof of concept to validate my assumptions and hypotheses. My expectation is that for the first few projects there will be parts written in TypeScript (out of practical considerations) and my hope is that over time, subsequent projects will see ReScript completely replace TypeScript.

3 Likes

GenType is indeed a great under-appreciated tool we have.

And yes, we do intend to be like Go (but with a type system that’s a bit richer, and with JS interop, and some design-driven orientation).

1 Like

Speaking of domain modelling, Scott Wlaschin recommends showing your types to domain experts. And since ReScript variants are less noisy and therefore more readable than TypeScript’s discriminating unions, I’d argue that this is one more reason why ReScript is better suited for domain modeling.

That, and the good old “If it’s hard to typecheck, it’s probably hard to understand”.

4 Likes

https://deno.land/ could also be an option maybe

2 Likes

Is this true? So you can’t build recursive types for lists and binary trees for examples? Will GADTs not be supported either?

We support recursive types and also recursive modules and functions.

GADTs are hard to explain, hard to understand, and we are not sure yet if it makes sense to trade clarity of the code with more expressive type constraint possibilities. GADTs are actually so meta that the Reason docs linked to an article called “Detecting use-cases for GADTs in OCaml”, which is always a good sign that a feature might be too complex for the broader audience.

Or as @chenglou put it:

we don’t try to be under-expressive but we also don’t try to be over-expressive and invent features that give you the tightest modeling of your domain (which is hardly a useful goal usually)

This might change in the future, but right now there are other priorities.

I will close this thread now, since the question has been answered and the discussion is kinda moving into different topics. (Feel free to open a new thread)

2 Likes