34 ms·
TypeScript vs. ReasonML
- pbowyer 7y agoI didn't think much of this article ("Another biased comparison, yawn") until I got to the Reducer example. I read up on reducers for Redux and Cycle.js, but avoided using them. The Typescript examples are so cumbersome; I'd rather do something else where my code is more understandable. But in ReasonML it's elegant. It's awesome! I'd choose to use that. Sure they do the same thing. But as the developer who has to commit to reading and maintaining this code, I know which I'd rather write and come back to in 18 months' time.
- quickthrower2 7y agoI wonder if people (including me) are too afraid to write a little DSL/compiler to get us out of these spots. I.e. use Typescript most of the time, with a DSL for things like reducers. Another thing where a DSL/compiler step would be good is to convert a type into a function that will validate arbitrary JSON (e.g. received on the wire) conforms to the type.
- rkangel 7y agoThe reducer is a case where the functional programming concepts like sum types make a dramatic difference, but they are widely useful across your codebase. It shouldn't be a surprise that React works well in ReasonML - the first prototype of ReactJS was written in StandardML before the creator ported it to JS (https://reasonml.github.io/docs/en/what-and-why.html https://reasonml.github.io/docs/en/what-and-why.html)
- undecidabot 7y agoLooks like another biased comparison to me. You could easily rewrite the TypeScript reducer example (which fails to compile btw) to be similarly concise while being as safe. interface State { movies: string[] } // you may also use { tag: "Action", payload: string } // if you prefer something more structured type Action = | ["AddMovie", string] | ["RemoveMovie", string] | ["Reset"] const defaultState: State = { movies: [] } const reducer = (state: State, action: Action): State => { switch (action[0]) { case "AddMovie": return { movies: [action[1], ...state.movies] } case "RemoveMovie": return { movies: state.movies.filter(m => m !== action[1]) } case "Reset": return defaultState } } const someAction: Action = ["AddMovie", "The End of Evangelion"] TypesScript's type system is actually very flexible and advanced [1] compared to most type systems since it had to adapt to the very "dynamic" structuring of JavaScript in the wild. [1] https://www.typescriptlang.org/docs/handbook/advanced-types.html https://www.typescriptlang.org/docs/handbook/advanced-types....
- hajile 7y agoReasonML variants are type constructors. Your example completely eliminated all action creators (constructors). Once you add those functions back, most of the type bloat reappears. I wouldn't want to work on a project where everyone was creating object literals and passing them to dispatch everywhere.
- mikewhy 7y agoThis is what my redux stuff looks like with TypeScript: const constants = { addMovie: 'movies/addMovie', } export const addMovie = createAction<string>(constants.addMovie) export const reducer = createReducer(initialState, { [constants.addMovie]: (state, action: ReturnType<typeof addMovie>) => ({ ...state, }) }) But this forgoes applying any constraints to `dispatch` / the ability to have one giant union of all possible action types your app supports.
- undecidabot 7y agoYes, I eliminated the action creators. I don't see why they're necessary (maybe there's something about redux I'm missing?). The type constructors of ReasonML cannot be used as functions, so I think my rewrite is fair. If you insist on having the action creators, they can easily be written as one liners each, which is a lot less bloated than the original example. export const addMovie = (movie: string): Action => ({ tag: "AddMovie", movie }); What's the issue with passing object literals? I know it looks a bit hacky and messy, but if it's typesafe (which it is) then it doesn't seem like a real issue.
- hajile 7y agoNo action creator is a serious refactor concern. Let's say you need to update your function signature with an additional, optional parameter with a default value. You can go to the definition of the action creator and change it. Since you've defined an interface for the action object, finding reducers that use it will be reliable and easy. If such a creator doesn't exist, you must grep your codebase for every instance of the object and ensure they deal with the optional bit. Murphy's Law guarantees that someone will have decided to procedurally generate the object making finding every instance very hard. Next, you have that reducer lookup, but you don't have a shared interface, so you're stuck in grep land once again to find all the reducers. Finally, copy-pasting an object literal all over generally results in a larger bundle than reusing an action creator which is smaller and also minifies better.
- philplckthun 7y agoIt's great to see more comparisons and articles about ReasonML and this one is really concise! But I do wish articles were more clear about the relationship between ReasonML, OCaml, and Bucklescript. > It is also interesting to look at what javascript was generated by ReasonML This is where BuckleScript should probably be mentioned first. TypeScript is both the name for the language and the tsc compiler, since it's a single project. But with BuckleScript that's not the case. > BuckleScript is the tool that transpiles ReasonML to JavaScript. There's also the older js_of_ocaml (JSoO) project, and there's more great Reason/OCaml tooling for native, like esy and dune! It's really exciting, but these small details are rather interesting and it's important to highlight them to avoid confusing beginners.
- k__ 7y agoAs far as I understood is esy uses dune and dune uses BuckleScript, so they aren't alternatives.
- brmgb 7y agoSadly, BuckleScript tries to do everything. It ships with a not so-great build system, a good compiler to javascript, a standard library replacement and it invites you to use npm for package management. Dune is the build system which has become the standard in the Ocaml community. It can use the native compiler or js-of-ocaml to produce javascript. It doesn't support BuckleScript however. Esy is a tool which allows you to manage your project dependencies. It can pick package from both opam and npm and uses Dune as a build system. It's actually very good. As Facebook mostly pushes ReasonML towards Javascript developers, they mostly advertise BuckleScript. From what I have seen, the Ocaml community mostly does not care about Reason. They had no issue in modifying tools to support it and noone is going out of its way to hinder it but there is no particuliar enthusiasm towards it.
- k__ 7y agoUnderstandable. For JS it's a step forward, for OCaml it seems to be a step back.
- pkilgore 7y agoI'm building a project in ReasonML right now with reason-react. The Reason-only parts are actually a joy. The problem is interop with the wider ecosystem, and bucklescript. They are serious problems. You end up writing a ton of [@bs.... ] annotations to get things to work together that ultimately result in runtime errors. I hate battling a compiler (with sometimes quite cryptic errors, particularly identifying syntax errors) only to find that I can't actually free myself from the same type of errors I'd see with regular old JavaScript. I can dig through my discord history and give more specifics. But given the massive learning curve and poor tooling that exists these days it's a step backwards from mainstream production JS development. That said, the community has really got some wonderful folks out there, and is very helpful. I hope they can figure out interop with basic JS like promises. And tooling. And let me use async/await. And make bundle splitting easier to implement.
- deathtrader666 7y agoYou could write your app using the Elm-inspired Bucklescript-TEA [0] framework in OCaml, and use js_of_ocaml to transpile OCaml into JavaScript. [0] - https://github.com/OvermindDL1/bucklescript-tea https://github.com/OvermindDL1/bucklescript-tea
- pkilgore 7y agoIn what ways does it fix my major issues with bucklescript (simple interop with JS libraries / object / output, promises, async/await being highest on the list).
- deathtrader666 7y agoWith js_of_ocaml, you need not use Bucklescript at all. Both are transpilers for OCaml -> JavaScript.
- wtetzner 7y agoIs Bucklescript-TEA available through OPAM, or only through NPM? EDIT: Nevermind [1] https://github.com/OvermindDL1/bucklescript-tea/issues/45 https://github.com/OvermindDL1/bucklescript-tea/issues/45
- Illniyar 7y ago>It is also interesting to look at what javascript was generated by ReasonML ``` function updateName(product, name) { return [name, product[1]] } ``` Records in ReasonML are represented as arrays. And generated code looks like a human wrote it if humans could remember indices of every property of every type like a compiler does. This seems like a massive headache, what about JSON? or accessing dictionaries? Do you need to parse every js datastructure to a ReasonML record?
- pkilgore 7y agoNo. Reason (bucklescript really) maps to the full range of a data structures. So use a dict as a dict, a record as a record, an array as an array...etc. It will map back to what makes the most sense in the JS world. As opposed to JS, where really all these things are overloaded onto the same data structure ( object ).
- pkilgore 7y agoBut to be clear, yes, interop with regular JavaScript and JSON is a bit of a pain in the butt. Bucklescript has lots of helpers but it's definitely the place where the soundness of the type system has broken down for me in the past.
- jbverschoor 7y agoIt's simply incorrect.. > Although I didn’t write any types by hand, the arguments of this function are typed. Why don’t we have to write types in ReasonML? let sum = (a,b) => a + b; Is perfectly fine for typescript too. As for: let formatName = product => "Name: "+product.name; So I stopped reading there.
- koolba 7y agoDoes ReasonML infer that a type "Product" is the only one in the visible namespace with a "name" property or does it infer at use time that the formatName(...) invocation is valid because the argument has a "name" property? They're separate concepts. Maybe I want to ensure that I'm receiving a product as it makes no sense to invoke formatName(...) on other things with names like a Cat or Person. And the generic "thing with a name" one is possible in TypeScript too: const formatName = (product: {name: string}) => "Name: " + product.name
- dmitriid 7y agoIIRC if there are several possible choices, the compiler will complain (with a fairly incomprehensible message), and you will have to explicitly provide the type. And this happens all the time.
- arthurbrown 7y agoThey're different concepts with different ways of being expressed in OCaml. In this case it truly is a Product and if you want to reuse a field name you'll need to enclose that type in a module. Row polymorphic -- "thing with a name" -- is possible through the object system which is accessed through a different syntax, and works like go interfaces in practice.
- masklinn 7y ago> Does ReasonML infer that a type "Product" is the only one in the visible namespace with a "name" property Yes. > does it infer at use time that the formatName(...) invocation is valid because the argument has a "name" property? No. OCaml does have a structural object system (https://v1.realworldocaml.org/v1/en/html/objects.html https://v1.realworldocaml.org/v1/en/html/objects.html) and it is available to reason, but it's syntactically funky (https://reasonml.github.io/docs/en/object https://reasonml.github.io/docs/en/object) and as far as I can tell TFA does not use it. > They're separate concepts. Yes. Which is why OCaml (and thus Reason) separates it[0] from the nominative "structures". > Maybe I want to ensure that I'm receiving a product as it makes no sense to invoke formatName(...) on other things with names like a Cat or Person. You're really deep into this strawmanning thing. [0] pretty completely, you can't use nominative types in a structural context, they are not compatible. In fact structural types are sets of methods, something which doesn't exist on the nominative side.
- lovasoa 7y agoI think the comparison in the redux example really isn't fair. He defines just one enumeration in ReasonML and uses many different constants and interfaces in Typescript. The equivalent of type action = | AddMovie(string) | RemoveMovie(string) | Reset in Typescript is more something like : type Action = | { type: "ADD_MOVIE", movie: string } | { type: "REMOVE_MOVIE", movie: string } | { type: "RESET"};
- nirvdrum 7y agoSince TS is just JS, you could just dispatch to arbitrary strings, but the TS type system isn't going to help you out very much. The approach the author is taking is the one described in the Redux documentation [0]. [0] -- https://redux.js.org/recipes/usage-with-typescript https://redux.js.org/recipes/usage-with-typescript
- acemarke 7y agoHi, I'm a Redux maintainer. FWIW, there's apparently a ton of ways to handle typing Redux with TS (and that's even reflected in the discussion for the PR that added that page [0]). A large part of it seems to revolve around whether or not you're trying to apply action types to `dispatch` to limit what actions can be dispatched. I'm comfortable with TS at a general level (declaring interfaces for API types, reducers, and React component props), but a lot of folks seem to go crazy trying to get 100% type coverage. I personally aim for more of an "80%" sweet spot for typing - trying to trade off overall benefit with not trying to tie myself in knots adding ridiculous type declarations. I actually just wrote a tutorial page for Redux Starter Kit that shows how to use it with TS and `useDispatch` [1], but had someone point out that one of the examples I was using for thunks was losing a bit of type safety [2]. This stuff is hard :) [0] https://github.com/reduxjs/redux/pull/3201 https://github.com/reduxjs/redux/pull/3201 [1] https://redux-starter-kit.js.org/tutorials/advanced-tutorial https://redux-starter-kit.js.org/tutorials/advanced-tutorial [2] https://github.com/markerikson/rsk-github-issues-example/pull/1 https://github.com/markerikson/rsk-github-issues-example/pul...
- 7y ago
- k__ 7y agoAnyone knows good ReasonReact tutorials where people build a full app?
- yawaramin 7y agoYes–check out this excellent blog series https://dev.to/seif_ghezala/reasonml-for-production-react-apps-part-1-3nfk https://dev.to/seif_ghezala/reasonml-for-production-react-ap...
- jameskraus 7y agoI wish this comparison included more information about the developer experience of TS vs Reason. In my off time I've tried out Reason, but one of the major sticking points was how _poor_ the experience was setting up an editor with autocomplete and type hints. You get that basically out of the box with TS, but Reason & OCaml have a more fragmented ecosystem, so it's much harder to get started and feel productive. IMO, the beautiful type system is nice, but the DX with TS is much more productive than Reason or OCaml. PS: Do you think my comment is dumb? Reason/OCaml are easy to set up? It's as easy as 1-2-3? Please link me tutorials or resources that prove me wrong. I'd love to get started, but DX has been the major hangup again and again.
- Dude2029 7y agoEvery technology created at Facebook is meant for internal use. The wider community then goes through the pain of making it usable. Microsoft's mission on the other hand is pleasing developers hence VS Code and TS.
- smt88 7y agoI remember when people got excited about Hack, Flow, and Nuclide (or whatever the Facebook IDE was supposed called), but eventually realized the same things that you and GP realized. Microsoft has paying customers who are devs, and FB doesn't. That explains a lot.
- k__ 7y agoAs far as I know BuckleScript isn't a FB project.
- chucksmash 7y agoIt isn't[1]. It's a "partner project" to ReasonML which ReasonML relies on[2]. [1]: https://www.bloomberg.com/company/press/open-source-at-bloomberg-introducing-bucklescript/ https://www.bloomberg.com/company/press/open-source-at-bloom... [2]: https://reasonml.github.io/docs/en/what-and-why https://reasonml.github.io/docs/en/what-and-why
- eatonphil 7y agoThe most pragmatic reason to use TypeScript is for gradual typing of existing codebases, and that all JavaScript is valid TypeScript. You can introduce TypeScript over time and if it doesn't work out for your group, you can delete the TypeScript-specific annotations and go back to Babel. Or you can keep TypeScript to only specific parts of your application/library. The most pragmatic reason not to use TypeScript is because it is static-only. And that is easy to forget. That is, within any arbitrary function X you have no guarantee the parameters passed to X are the type specified in TypeScript. There isn't a ton you can do about this except for to code very defensively where it matters. I've used TypeScript for a number of projects professionally, introducing it among developers familiar and unfamiliar with static typing. I'm not really interested in going back or finding alternatives for now. It is a huge help in development and refactoring without a huge cost.
- siempreb 7y ago> and if it doesn't work out for your group, you can delete the TypeScript-specific annotations and go back to Babel. You are joking right? Ever tried to do that with a large Typescript code base and then of course without the defensive strategy? It's a myth Typescript proponents really enjoy to believe. > There isn't a ton you can do about this except for to code very defensively where it matters. Bingo! That's what I always did and served me well on very large code bases. With Typescript I have to write about 20% more code(that can hide bugs too). Advantage? A bit more intellisense than VScode gives already out of the box, and of course for the junior and medior developers so they cannot mess up(types).
- eatonphil 7y ago> Ever tried to do that with a large Typescript code base and then of course without the defensive strategy? It's a myth Typescript proponents really enjoy to believe. You got me. I have not tried to do this in a large TS codebase. > There isn't a ton you can do about this except for to code very defensively where it matters. Of course you have this issue in pure JavaScript too. So it's not so much that TypeScript is worse it's just not as big an improvement in this regard as a compile-to-JavaScript language that gives you runtime type safety.
- redleggedfrog 7y agoI think where these comparisons go wrong is tooling. I don't give a rodent's behind how nifty your new language is unless you've got excellent tooling, particularly, an easy to use step through debugger (and no, you still need a debugger when functional programming). The second I think I'm doing printf() debugging I'm out. Note, I'm only referring to actually getting work done here - academically, or if you're just dinking around, then it's all good.
- loxs 7y agoThis, and also proper out-of-the-box IDE for refactoring, completion etc. Reason/OCaml do have the proper IDE, just not out-of-the-box.
- cjdell 7y agoI tried really hard to use ReasonML about a year ago but ran into a road block with the lack of async/wait (or equivalent) syntax. It's really cumbersome to have to go back to chaining callbacks again.
- dmitriid 7y agoThe problems I ran into with ReasonML (last year) is how scarce the ecosystem is and how incomplete the bindings. I remember trying to fetch stuff. Fetch wrapper returns data in a type that is not convertible to anything. Ex. it returns Fetch.Uint8ArrayBuffer instead of Uint8ArrayBuffer. Because reasons. And the compiler was entirely unhelpful. “X provided but somewhere required Y” is the best you could get for type errors. Somwhere... where? ReasonML is very very early on adoption curve.
- kangar00857 7y agoI understand it’s a major sin to ever talk about syntax but a lot of ReasonML reads like someone’s cat walked across the keyboard This project is interesting & the folks evidently involved & advocating invested a lot time + smarts but why bother with all this new cognitive load & new universe of subtle problems (bucklescript, interopt, external libs, etc)?
- kangar00857 7y ago(Not trolling, no flamewar but asking out of curiosity) Is ES6 + Typescript in 2019 really so awful that all this effort is required to build rich applications for web? Perhaps ReasonML is like “the big guns”, but what situation makes it necessary/important/better to use?
- jasim 7y agoThis might shed some light: https://www.harigopal.in/talks/2018/jsfoo https://www.harigopal.in/talks/2018/jsfoo
- sweeneyrod 7y agoIt's a matter of taste. Syntax isn't an issue if you're used to OCaml (which arguably has worse syntax -- semicolon as a list separator!) so there's no problem for that section of the userbase. I don't know how people coming from JS generally feel.
- lucaspottersky 7y ago> "And while having that familiarity with JavaScript is nice, it means that every quirkiness that we love and hate about JavaScript is still there in TypeScript > "... ReasonML is everything TypeScript tries to be (and a bit more) without all that JavaScript weirdness." yeah, but what makes the author think that __INSERT NEW LANGUAGE HERE__ would not have other 'quirkiness'?
- blunte 7y agoYes please! I would absolutely rather use ReasonML than TypeScript or JavaScript; so I hope it gains a lot of traction. I'd still rather use ClojureScript, though.
- jecxjo 7y agoCan I ask why? I came from low level language background but my "fun programming" went from Lisps to MLs and now I have difficulties going back to Lisps for projects. Always wanted to like Clojure but never had a need for JVM in anything I worked on.
- blunte 7y agoMy little brain can't keep up with too many things (in short term memory) at once, so more concise and expressive languages are better for me. Also, more sane languages are better (where it's harder to shoot yourself in the foot because you're not (yet) very good at the language). The homoiconicity of Lisps allow me to think less about syntax. (function <args...>). And reading code is easier, since I see the operations first. Adding more advanced features (via macros) can give you lovely function chaining - threading, piping, etc. Immutability in Clojure is also good for me because it allows me to learn and forget about functions. Black boxes are great things when you can trust that they are pure functions; just compose bigger black boxes and so on. I don't do a lot of Clojure these days, but when I was using it professionally I could basically forget about JVM; JDBC was about the only time I interop-ed with Java. If you need some of the good things that JVM offers, great; if not, it's just a hosting environment. Same with Elixir and BEAM (although JVM and BEAM are very different and tailored for different problem sets). But on topic, given a choice between ReasonML and JavaScript, it seems to me that ReasonML is more thought out, cleaner, safer, and a step in the right direction.
- hota_mazi 7y agoMy little brain can't keep up with too many things either, which is why I only use statically typed languages. Dynamically typed languages force me to keep type information in my head, and that's just not a good use of my brain when the compiler can be so much better than me at this.
- philliphaydon 7y agoI’m not a fan of TypeScript, and never heard of Reason, but this post makes me like TypeScript more. I prefer the fact it’s more explicit and less magic. The examples in TS are very easy to understand where Reason just looks like magic and I have to think more about what it might be doing. I don’t see a benefit to Reason over vanilla JS. /opinion
- wry_discontent 7y agoThat basically amounts to "I have learned Typescript and not Reason, therefore Typescript is better." I'm not a Reason pro, but it doesn't look magical to me. It seems just as explicit, and actually more so in the reducer example.
- Rapzid 7y agoF# tackles this disconnect between working on the code in an IDE and reading code with an interesting documentation system: https://fsprojects.github.io/FSharp.Formatting/metadata.html https://fsprojects.github.io/FSharp.Formatting/metadata.html . Mouse over the code :)
- devmunchies 7y agoi hate those tooltips when they get in my way. I wish they only showed up if you hold control + hover or something like that.
- eptcyka 7y agoI'd argue that's because ReasonML/Buckle is a completely different language whereas Typescript is a superset of JavaScript. I don't believe that one is inherently more legible than the other, but you might have trouble reading Reason if all you know is C-style languages.
- crimsonalucard 7y agoYou need to study ML based languages like Haskell and reason to see why reason is actually more explicit then type script. It takes some effort but in the end you'll have a better understanding of programming in general. Typescript is missing the Variant type primitive so it has to be written in a roundabout way to imitate that primitive (and it most likely isn't type checked correctly either). The extra code you are writing in TS is not explicit... a better term is obfuscates.
- indeyets 7y agoI wonder how ReasonML is positioned against Flow. Both seem to fill the same niche at facebook (and both lack marketing resources of TypeScript).
- tomp 7y ago> Why don’t we have to write types in ReasonML? Because of the powerful type system that allows for incredible type inference. You mean the restricted type system that allows for principal type inference? ML's type system is much less powerful than Haskell's or Scala's, precisely to allow type inference (e.g. no overloads). The type inference itself isn't very powerful or incredible either, it works just for the exact type system offered by ML. Obviously nobody likes this, which is why ML offers a number of hacks to allow more powerful type system hackery - e.g. open sums ("polymorphic variants" and also open exception types), HKTs (modules), GADTs, row types & subtyping (objects). Although IMO it would be better to incorporate all these hacks in the core language itself, and only run type inference on the bits where it's possible (but of course tradeoffs would be necessary to avoid running into halting problems etc.).
- sweeneyrod 7y agoYes, that sentence should've probably been "Why don't we have to write types in ReasonML? Because of the powerful type inference system". But I think comparing to Haskell is kind of missing the point: you can't use that for front-end web development. Also, I'm not sure what you mean by saying those "hacks" aren't part of the core language.
- tomp 7y agoBy “hacks” I mainly meant that they don’t play that nice with type inference... type annotations are sometimes needed. Also that they were added to the language later, in order to make the type system more powerful.
- ernst_klim 7y ago> number of hacks These are not hacks, subtyping and GADT are part of the core language > ML's type system is much less powerful than Haskell's or Scala's Yes, but most of the fancy stuff is located in the module language, and it doesn't lack power, it lacks implicitness (until modular implicits would land).
- yawaramin 7y ago> ML's type system is much less powerful than Haskell's or Scala's That's arguable. What's not arguable is that every OCaml compiler runs circles around GHC and scalac in terms of compilation speed. If you like not waiting for the compiler, then you should like OCaml.
- stephen 7y agoI inherited several Flow codebases, which is from the same guy/group as Reason at FB, and attempted to do the same goal of "bah explicit type annotations, let's infer everything". This nearly ruined the codebases and we ended up converting them all to TS because: A) tactically, flow's global inference sucked, so many things that devs thought were typed, were not. I get they're trying a do-over and using OCaml to solve that this time around, which I agree is fundamentally a better approach. B) strategically, explicit type annotations (i.e. at method boundaries) is a _feature_ for dev readability and comprehension and not a burden to be avoided. I get that Flow/Reason _can_ add these type defs, but many new devs see posts like this, think "nice, less chars to type!", and now write a 100k LOC codebase with a pervasive lack of any type defs. Tldr, I think TS's explicit types at boundaries is actually best practice for programming-in-the-large.
- toolslive 7y ago> explicit type annotations (i.e. at method boundaries) is a _feature_ for dev readability and comprehension and not a burden to be avoided The problem is not the type inference, but tooling. If your IDE can, when you're coding can 'show-type-at-point' and your online github style code review tool shows the type of any expression, argument, ... when you hover over it, you no longer have this problem.
- spoiler 7y agoA was a bug. Previously Flow when certain errors happened internally, Flow would "demote" a type into `any`, but that's been fixed for quite some time now.
- Allower 7y ago>(+) operator in ReasonML works only with integers — the only type that a and b can be, so we don’t have to write them Well thats pretty stupid..
- thekillerdev 7y agoWhy don’t we have to write types in ReasonML? Because of the powerful type system that allows for incredible type inference. wat? https://www.typescriptlang.org/docs/handbook/type-inference.html https://www.typescriptlang.org/docs/handbook/type-inference....
- a0 7y agoMany modern languages support type inference to some degree. The special thing about ReasonML is that the type inference is much more robust and complete. In practice you don't need to provide any types annotations at all at any point in your program and you should still get the same safety benefits. Every value in your code will automatically have one single type assigned to it based on how it is being used. When the compiler finds contradictions it will let you know about it. On the other hand, Typescript will try to unify the type to some sort of Any, which is probably not what you want.
- gridlockd 7y agoWhy do people care about this? Writing type annotations is not that much work, but they make your code more readable. I can see the argument for it when you have unspellable nested generic types, or when you don't want to write the same thing on both sides of an assignment. Simple type inference like in TS gives you that. Having really smart type inference makes your compiler slower and more complicated. What's the real-world benefit? > Typescript will try to unify the type to some sort of Any, which is probably not what you want. Not really, unless you push the type inference beyond its limits, in which case you should just change your code.
- a0 7y agoMany interesting points! :) > Why do people care about this? Writing type annotations is not that much work (...) I personally care about this when I'm prototyping something. Not having to write types means that I can simply write what's on my mind. The benefit of good type inference is that the compiler can still help me highlight any mistakes I made during this process. Another benefit is that some production code can get very complex. Having to type every single value is just too cumbersome and distracting. It contributes to boilerplate and increases cognitive load, in my opinion. > Having really smart type inference makes your compiler slower and more complicated. I would actually disagree with this. First of all, ReasonML's compiler is absurdly fast. No, seriously try it. Sometimes I go and double check the generated JS code just to be sure it actually did anything. Regarding the "more complicated" part – the only reason why full type inference works is because it is based on a very solid theoretical foundation. It might be somewhat "complicated", but it will never be as complicated as something ad-hoc that needs to account for all inconsistencies that exist in untyped languages like JavaScript.
- grumpy8 7y agoIMHO the biggest reason to use TypeScript rather than Reason is because, in the end, it's still javascript and it stays within the same ecosystem. As great as Reason is, it's adding too many dependencies. The only time I'd go with Reason instead of Typescript is if the developers on the team are already proficient with OCaml. It's going back to the "Use boring technologies even though some things suck as it's better to deal with known issues than unknown issues; the grass isn't always greener with new technologies, just different things that suck".
- StreamBright 7y ago>> in the end, it's still javascript This is exactly the reason I prefer Reason. :)
- gridlockd 7y agoReasonML is also just Javascript in the end, dealing with the same platform limitations.
- s_y_n_t_a_x 7y agoYou can rename a JS file to a TS extension and it's TypeScript. The annotations are replaced with whitespace when JS is generated, it doesn't result in different code.
- gridlockd 7y agoBeing as close as possible to JS for transpilation is a design goal of Typescript, but the compiler still does more than just strip away the types if you use certain language features. If it was just about stripping away types, then there wouldn't be a need for a compiler and the type checker could be a separate program.
- WorldMaker 7y agoYou can already run Typescript type checker separately from a type stripper today, though. Typescript has babel plugins for exactly that. Almost all webpack best practices for Typescript involve the fork-ts-type-checker plugin, running type checks in a separate thread from the transpile phase. At this point almost all of what Typescript compiles (transpiles) that isn't just "type stripping" is some form of downleveling from current ES standards to older ES versions and is almost all entirely optional. There's also nothing stopping you from leaving it all to Babel to do it instead of having Typescript do it, if you wish. (Though personally, I think Typescript is a lot lighter weight a solution than most Babel presets and tslib (the optional dynamic link version of the inline downlevel helper functions TS emits) is a lot smaller than Babel's equivalents in core-js.)
- gridlockd 7y agoNone of these are worth switching to a fringe ecosystem for. The compile-example is misleading. Clean build times don't really matter. Iteration times with "tsc -w" would've likely been well under a second. The boiler-plate in the redux example could be reduced, but redux itself is extremely boilerplate-heavy when written in this explicit style. It would be interesting to see how the ReasonML typesystem gets in the way of metaprogramming.
- a0 7y agoOne place where clean build times do matter is in the CI. Having very fast builds and tests is great for speedy deployments.
- sikan 7y agoAt work our TS project with a thousand files takes 30mins on CI, incremental save takes at least 20 second. Half of the time makes the machine run out of memory. Bucklescript can have a clean build of 1.2k files project in under 4 seconds! https://twitter.com/bobzhang1988/status/1160846763747508224 https://twitter.com/bobzhang1988/status/1160846763747508224
- gridlockd 7y agoThanks for the data point. Those aren't the same thousand files though. If your project has a thousand source files of any programming language, it's probably time to quit and join a younger company.
- rambossa 7y agoHow is dev ex with Reason? Intellisense?
- a0 7y agoIt's ok. There's pretty good support for linting and code completion. The plugins are fast and have a rich feature set. Take a look at this: https://marketplace.visualstudio.com/items?itemName=jaredly.reason-vscode https://marketplace.visualstudio.com/items?itemName=jaredly.... The only problem that I have found is that in some situations it doesn't report errors correctly when adding new dependencies. Refreshing the window or rebuilding the project usually helps. On the other hand, the compiler feels very solid. It can be annoying in the beginning because of how disciplined the code needs to be, and the error messages can be hard to understand. After getting used to that, the dev ex is really smooth specially during complicated refactoring, the compiler and the IDE make things almost boring.
- muglug 7y agoI get the sense that ReasonML exists because some smart people see "JavaScript developer" as a pejorative. While its abstractions make plenty of sense, its distance from JavaScript makes it incredibly unappealing to the average developer.
- azangru 7y agoWhy should we concern ourselves with psychological processes of the mythical average developer? The question is, whether this language is appealing to you.
- muglug 7y agoI suppose if you're working on a small pet project that nobody else is going to see. If you're working on something with a bunch of other people you're likely to care more about what the mythical average dev thinks.
- a0 7y agoThis kind of comments make me really sad. Most ReasonML developers are actually "JavaScript developers". ReasonML was specifically designed for JavaScript developers. Being JavaScript-friendly is in it's DNA really. I even see ReasonML a language that was specifically designed to work with React. I can understand why you would feel this way though. I think the main problem is that ReasonML introduces new concepts that simply do not exist in JavaScript. Learning those concepts is hard. But if it wasn't hard, would you be learning anything or just writing JavaScript in a slightly different way? Are there any specific examples of things that look too "distant" from JavaScript? I'll finish this by saying that ReasonML will make you a better JavaScript developer. As will probably learning any other language that challenges the way you think.
- muglug 7y ago> I'll finish this by saying that ReasonML will make you a better JavaScript developer. As will probably learning any other language that challenges the way you think. I wholeheartedly agree! But a lot of people don't want to be challenged by the language when there are already plenty of other challenges in their personal and professional lives. With TypeScript you don't need to think half as much, and the thing your boss generally cares about (whether the feature shipped) gets done.
- truth_seeker 7y agoYet another day, yet another incomplete and immature language comparison blog ! I really wish to see some mature blog post which in depth covers the merits of languages in comparison by writing a large enough and workable piece of code solving the identical problem and utilizing all features of individual languages in their specific codebase. If the author would have been really unbiased about TypeScript he must have mentioned at least 2 (but not exhaustive) following things. 1. Advance TypeScript Types https://www.typescriptlang.org/docs/handbook/advanced-types.html https://www.typescriptlang.org/docs/handbook/advanced-types.... 2. Number of existing JS libraries TypeScript already supports https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types https://github.com/DefinitelyTyped/DefinitelyTyped/tree/mast... Most people are just stuck with ES5 and callbacks. I have conducted many (about 12 so far) meetups here in India on new features of ES6/ES7/ES8 and using them to build small full-stack JS/TS assignment with TDD for various kind of senior devs coming from Go, Java, Scala, Python and Ruby. Common reaction from them I receive very often "We never knew that JS/TS can do that"
- a0 7y ago> Common reaction from them I receive very often "We never knew that JS/TS can do that" Maybe it's about what you cannot do in ReasonML, and not about what you can do in TypeScript? :)
- nirvdrum 7y agoThe author mentions DefinitelyTyped: "DefinitelyTyped typings amount is just insane and it will take time for ReasonML to match them." I agree it would be nice to have an expert analysis of a reasonably-sized application, but that is a rather large undertaking. And frankly many devs aren't experts in two "competing" ecosystems. If you spend the bulk of your time in ReasonML, you're apt to fall behind on TypeScript's recent developments. What you see as bias may just be simple ignorance. I've just started playing around with ReasonML in the past week, and everything the author has hit upon has been relevant. Writing reducers in ReasonML is a treat. But, the language server isn't nearly as good and there aren't many annotated libraries, so I have to fall back to BuckleScript's JS interop support. The interop system is well-done, but it's extra overhead I wouldn't have to deal with otherwise.
- Can_Not 7y agoWould love to use typescript or ReasonML with something other than react, like svelte.
- deleted 7y ago[deleted]
- devmunchies 7y agodoesn't say this in the post, but ReasonML was created by the same developer that created React. Which would indicate it is good for generating UIs in the browser but not necessarily all the other stuff JS does (interacting with browser APIs and stuff) I'm a big fan of OCaml, so I would like to see more developers dogpile on a functional UI language like ReasonML so it improves.
- duckqlz 7y agoGreat comparison I was interested in reasonML and find comparisons like these very helpful. Still sticking to ELM for my personal projects!
- crimsonalucard 7y agoELM really needs type variables and type classes.
- hashbig 7y agoAnything declared in Elm is immutable so types on constants become way less relevant.
- crimsonalucard 7y agoType variables are not what you're thinking. add :: Int -> Int -> Int add a b = a + b add2 :: a -> a -> a add2 c d = c + d 1st function adds integers. 2nd function adds anything that can be added. For example: add2 [1,2,3] [4,5,6] evaluates to [1,2,3,4,5,6] The 'a' in the second function is a type variable.
- waltera 7y agoI got interested in Reason last year after reading lorefnon's article [1] comparing Reason with TypeScript. Recently, after evaluating both for a large project we decided to prefer TypeScript primarily because TypeScript's support for intersection types, mapped types and conditional types is really awesome and make integration with javascript libraries a lot easier. As far as I could find, similar things can't be done in ReasonML at all (although I could be wrong on it). The tooling integration of TypeScript is also really awesome. Besides the usual refactoring, jump to definition support etc. a lot of effort has gone into small things that makes life easier. For example, if you have ctrl+click on a mapped type's property it will jump to the original type being mapped. In libraries like io-ts if you add doc comments on methods which are used to derive the types, the documentation will be propagated to the derived types [2]. I recently found that the author of the above post has been experimenting [3] with babel-macros [4] to facilitate nice type-safe fluent APIs/abstractions which are compiled away to simple readable javascript with zero/negligible runtime overhead and found it a really neat idea. Looking at some of that code, it appears to be a lot simpler than writing ppx macros [5] for ocaml which I very briefly experimented with. [1] https://lorefnon.tech/2018/05/13/reasonml-vs-typescript-first-impressions/ https://lorefnon.tech/2018/05/13/reasonml-vs-typescript-firs... [2] https://github.com/gcanti/io-ts/issues/201#issuecomment-434721076 https://github.com/gcanti/io-ts/issues/201#issuecomment-4347... [3] https://github.com/ts-delight https://github.com/ts-delight [4] https://github.com/kentcdodds/babel-plugin-macros https://github.com/kentcdodds/babel-plugin-macros [5] http://ocamllabs.io/doc/ppx.html http://ocamllabs.io/doc/ppx.html
- bkonz 7y agoWhile I can't speak specifically to ReasonML, I have used Ocaml and Typescript extensively in https://www.jeroo.org/beta https://www.jeroo.org/beta. I used Ocaml to write the a (simple) custom compiler framework, which gave me the benefits of better type safety than Typescript. Typescript was used with Angular to create everything else (the custom-bytecode interpreter and user-interface. Typescript gives me the advantage of good interop with Javascript libraries, mainly CodeMirror for the editor. The interop with Ocaml and Typescript was pretty good. I just exported the Ocaml as a Javascript module using Js-of-ocaml with one exported function that starts off the compilation. Then it returns a list of a custom instruction object, which acts as a 5-tuple with all of the instruction fields.
- loxs 7y agoAfter one year of OCaml/ReasonML and after that one year of TypeScript, I will not go back to Reason. 1. TypeScript has a better (more practical) type system (for the task of writing a WEB UI and interop with JS). 2. TypeScript is actually usable by people who do not have a PhD in type theory. 3. TypeScript has tools. This is a huge difference. 4. It's faster and cheaper to actually develop a product in TS than in Reason/OCaml. 5. Yeah, TS lets through more bugs, but it's actually just a small blip on the radar. In practice, TS makes it quite possible to get all of the benefits that OCaml claims without actually paying any real price. edit: formatting edit2: I still do use and love OCaml (on the backend), just not fooling myself I can actually ship a real (and big) web UI project using it.
- city41 7y agoThe article mentions a non handled case in a switch is flagged in Reason but not TypeScript. That is technically true, but you can flag an unhandled case by adding a default case which takes advantage of the never type https://stackoverflow.com/questions/39419170/how-do-i-check-that-a-switch-block-is-exhaustive-in-typescript https://stackoverflow.com/questions/39419170/how-do-i-check-...
- loxs 7y agoThis isn't needed any more. Modern TS enforces switch exhaustiveness out-of-the box (if you provide the proper union type, of course).
- city41 7y agoOh awesome, I didn't know that. Thanks for the heads up.
- sikan 7y agoThis is not true: https://www.typescriptlang.org/docs/handbook/advanced-types.html#exhaustiveness-checking https://www.typescriptlang.org/docs/handbook/advanced-types....
- loxs 7y agoYeah, I always use strict and specify return type. IMO, still counts.
- cztomsik 7y agojavascript/typescript is great if you don't know what you're going to eventually come up with but you need to iterate fast and keep it high-level with lots of TODOs and uncertainties which would otherwise have been hard to type. if there's anything I really, really hate it's when I'm just trying something and keep getting compiler errors for things I'm not even interested ATM.
- rictic 7y agoI love languages, and I want to use languages with powerful, sound type systems on the web, but I don't want to do it at the cost of shipping much larger amounts of code, making for a slow initial render. A vanilla JS todomvc app is 10KB of JS (plus some analytics code for some reason): http://todomvc.com/examples/vanilla-es6/ http://todomvc.com/examples/vanilla-es6/ The production build of the ReasonML todomvc app ships 5x as much, 56KB JS. How much of that is a static runtime cost, and how much is just the cost of translating ReasonML into the corresponding JS? An extra 40KB isn't great, but it's not a dealbreaker. A shipping 4x-5x as much JS would be, in a lot of cases.
- chenglou 7y agoEh where did you see that? ReasonReact is runtime-free, unless you’re explicitly using some of the extra helpers.
- rictic 7y agoI ran the production build of https://github.com/reasonml-community/reason-react-example/tree/master/src/todomvc https://github.com/reasonml-community/reason-react-example/t... and ran the JS bundle through gzip -9 to get the 56KB number.
- chenglou 7y agoOh man, that repo's stale. The official instructions are here: https://reasonml.github.io/reason-react/docs/en/installation https://reasonml.github.io/reason-react/docs/en/installation
- yawaramin 7y agoIf the ReasonML TodoMVC app was using the same basic approach as the Vanilla JS app, there is no way it would be shipping 5x as much code. ReasonML code compiles pretty much 1-to-1 to JavaScript. It does pull in a bit of a runtime if you use some standard OCaml libraries, most of that should be quite easy to eliminate with a good bundler.
- crimsonalucard 7y agoIn mathematical theory, the variant type is actually the theoretical opposite of a "struct" type. Mathematicians know this through the functions that apply to each type. Simply inverting the direction of functions that describe a "struct" type creates a structure that exactly describes a variant type. The theory points to opposites but language writers, unaware of theory, more often than not leave out the critical primitive that should be intrinsic to all programming languages.
- rammy1234 7y agowhen comparing the language construct, usually adoption is hindered by tooling. You should also compare tooling. that said, this is an excellent article trying to reason out why we should start using ReasonML
- lucasmullens 7y agoFor the "Null, undefined vs Option" part, it's feasible with a lint rule to ban null throughout your code. Might not work for third-party code, but Reason can't work with that anyway.