Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Decaffeinate converts CoffeeScript projects to modern JS (github.com)
361 points by alangpierce on June 19, 2017 | hide | past | web | favorite | 219 comments

I don't understand the trend to move from Coffeescript to ES6. I like both, but I write Coffeescript for its concision. I have no issue compiling Coffeescript to ES6 as a separate build step, but I'm not going to write ES6 myself. That said, I'm sure a project like Decaffeinate has brought a lot of beloved Coffeescript projects into the hands of ES6 developers who wanted to contribute.

ES6 has eliminated most (though not all) of the pain Coffeescript solved. I work on a large code base that went from Coffeescript -> Typescript (mostly manual, some decadfeinate), and typesafety has been a huge boon for our developers. For smaller teams/codebases, you might be happy sticking with Coffeescript.

I see ES6 or especially Typescript as essentially a recreation of ES4/Flash AS3, with some renaissance-era Javascript footguns attached. You've got classes, various class based OO features, optional typing major industry support, probably improved performance coming soon, etc...

Coffeescript was a bit different. It meant fewer lines of code, not more. It had significant whitespace and some other Python-inspired idioms like array comprehensions and object comprehensions. Most importantly, Coffeescript was a new language and didn't have to re-implement deleterious Javascript features like the == vs === distinction, undeclared vars leaking to global scope, baroque keywords like "with", etc...

That said as others have pointed out, ES6 did borrow many good features from CS and CS is slowly dying. Fortunately other languages like Elm and, to a lesser degree, Reason have offered even more compelling "footgun free" alternatives.

> It had significant whitespace and some other Python-inspired idioms like array comprehensions and object comprehensions.

Modern JS has standard HoFs (on arrays) and an iteration protocol.

> undeclared vars leaking to global scope

Strict mode (which syntactic ES6 features enable by default e.g. class contents are in strict mode always).

> baroque keywords like "with"

Which can trivially be linted away.

> ES6 did borrow many good features from CS

Not really from CS, rather from similar (much older) sources CS got them from.

HoFs are not array comprehensions and array comprehensions aren't supported in ES6.



> HoFs are not array comprehensions and array comprehensions aren't supported in ES6.

Neither of these is a claim I made so I'm not sure why you feel the need to point these out.

However native HoF obviate much of the need for comprehensions, especially combined with terser "arrow functions". Languages like Smalltalk or Ruby do just fine without comprehensions for instance.

If you quote the fact that coffeescript has significant whitespace, list comprehension and then in response say that javascript has HoF and iteration protocol, it does sound like youre trying to counter the point, so it seems like for someone to bring up the fact that they are not identical is fair game.

I inherited a coffeescript codebase a few years ago and found that it had footguns of its own due to a weak transpiler.

You're looking at the wrong bits. ES6 has delivered vast FP improvements and awesome async support.

The only async support in ES6 were standardised promise objects and arrow functions (which cleanup the callback-heavy promise-based code). As well as extensive promisification of browser API but that's not directly ES6.

Uh, did you notice the "async"/"await" keywords?

EDIT: My mistake. I learned something today.

That's not ES6. It's ES2017, aka ES8.

It's a bit presumptuous to tell me what bits to look at and then tell me about FP improvements when I just recommended Elm :D

So want typing support in CoffeeScript...

That was a big part of my motivation in building http://LightScript.org as it was clear that was never going to happen with coffee.

Currently works with Flow syntax, but not yet the actual flow checker - would love help making that happen!

That'd be particularly difficult as CoffeeScript doesn't have var declarations.

Partly. You can define them if you want it. You can even add type support with FB Flow.

CS developers sometimes define variables because of hoisting.

Obviously, variables are defined. In CS they are simply defined for you automatically. That said, you can obviously do it yourself if you want. But you will not be able to use additional tooling around `let` and `const`

Can one use FB flow with CoffeeScript? Comments I saw on github indicated that the CS compiler mangled it, I think due to how functions are named and stripping comments?

I personally don't really like types, but I've successfully used FB Flow with CS and it was fine.

Got any docs/writeup for this? Any tips/tricks/hacks?

It's not hard to understand. There's a cost to being in a community that's 1% the size.

The benefits were mainly for Ruby devs coming to Node from Rails, and were easier to see before JS itself added most of the syntax conveniences that Coffeescript introduced.

And don't underestimate the cost that comes with a) having to justify your quirky Coffeescript codebase to potential hires and b) not getting the hires you want because they won't work in Coffeescript. This was my main motivation for leaving it behind, even though I prefer the Coffeescript syntax over ES*.

True. I've declined job offers based on their use of CoffeeScript

And I totally believe that. I hated CoffeeScript with a passion since the moment I first laid my eyes on it.

To give an idea of how much I dislike it, I would prefer to write plain Javascript. To me, CF looks like a bad attempt at inheriting Python's whitespace-to-delimit-blocks. Function calls are confusing, they hurt my eyes.

To be honest, I wouldn't be interested in hiring someone whose entire line of reasoning in rejecting a programming language boils down to "function calls look funny, they hurt my eyes". So I guess that's a win-win.

It's a niche language that offers almost no reason to choose it over the most popular programming language in the world. As a niche language with a small community, the default opinion should be that someone is unlikely to want to work in it unless there is some coherent benefit to doing so

The problem with this line of thought is that it requires every shop to start migrating off of libraries just because they're going out of fashion.

Tech is an ecosystem, you can make just as much money off dead trees as you can off of killing wild boars. Coders who can work on both legacy and brand-new applications are the most versatile. If you think your skills are being neglected just because you're on Rails instead of Node or Elixir, or CoffeeScript instead of ES7, you've got a hard career ahead of you.

Migrating has a cost, and staying on old tech that nobody wants to learn anymore also has a cost.

The lesson isn't to migrate every year to the new hotness, it's to pick proven tech that is going to still exist in ten years. The Lindy effect applies.

Fewer technologies, with better support and bigger communities, are better than a fragmented ecosystem.

Fringe technologies come and go. The only reason to bet on a fringe technology is if you see major advantages, and in that case it is unlikely to remain fringe. Once it has been around for a few years and adoption is flat or dropping, yes, it is time to move on. That's just the cost of making a bad bet.

The number of technologies you can learn in your career and really master is limited. Too many people forget that.

For real. It's hard to imagine somebody so fulfilled in their lives that the only way to move the needle is to go somewhere with that perfect tech stack.

And not taking the job isn't even the best way to solve that problem. I'd ask them how married they were to CS and if moving off of it was doable.

If the shop is reasonable they won't have any objections so long as you're not hurting delivery targets to pursue your pet project. If they're not reasonable then you've found out a very important fact about that shop and that in itself can be a deal breaker.

I talked myself out of a job offer once when I stated that my main motivation for jumping was to work on a more well-maintained codebase. Kinda glad I did, but it was a wake-up call. If I'd tried to pull that shit when I didn't already have a great job, that would've sucked.

> I'd ask them how married they were to CS and if moving off of it was doable.

See, that's something I would never do. I dislike your tech stack, and if I can I will stay away from you. Why would I want to ask you to change it?

The tools one uses are one of the countless factors that influence their happiness. Therefore, if I think CoffeeScript and Angular suck balls, I will at least try to stay as far away from them as I possibly can.

It's not a matter of being "so fulfilled in their lives", it's just that I like to work with tools that have a higher chance of making me happier.

I would never allow a new dev to come in and ask us to completely move away from a tech stack in a project that we're already underway in.

It's one thing to try something different in a new project if it can legitimately solve problems we've been having in old projects.

But this idea that you can do that and most "reasonable people" are going to get behind you on it is balderdash. Most reasonable people are going to tell you no because there's not a strong reason to.

Much better to just move on if you don't like the tech they're working in.

And this is coming from someone who dislikes CoffeeScript, and always has. I would never suggest an active project rewrite their CS in something else.

Fair enough. If I can choose between a shop that uses A vs B, where A is something I like and B is yet another link in the toolchain that gives me more trouble that it solves, I will choose the former rather than the latter.

And no: unlike someone else suggested down here, I won't suggest you move away from a technology just because I don't like it. If you like it, keep it. If it's needed, I will adapt like I always did.

Just to put things into perspective, I recently had to do maintenance on an accounting app written in Visual FoxPro, which is another cobbled up piece of absolute shit. I hate it, and yet I did it. I can do and did the same with CoffeeScript, but if I can help it I will gladly avoid it.

Which is funny because its basically the position taken by those on both sides of this argument

It looks like Microsoft's TypeScript is the new hotness (static types! just like Java and C++, but better), and it's only compatible with ES6, not Coffeescript.

Typescript is a fantastic language with an absolutely horrid, bug-ridden configuration, tooling and ecosystem integration side. I say this after working with TS on a project for over a year now.

In particular, attempting to use it with npm modules is an exercise in tedium, as its module resolution constantly breaks and bizarre, undefined behavior does not stop happening. I've found dozens, maybe hundreds of similar reports online, with no solutions offered. There are all sorts of arbitrary gotchas with its configuration as pertains to this and other things. "Oh, don't use outDir and it'll work."

While it has great and straightforward integration with VS Code, it has disastrous integration with Visual Studio 2015 and 2017, the latter of which does not even support updating the bundled TS version at will without registry hacks. While TS emits code even in the case of errors, in many situations, Visual Studio refuses to complete the build process in case of TypeScript errors.

For an ES6+->ES5 transpiler, it is also very strange in that it polyfills some things but not others, such as Promises and Maps.

TypeScript has ultimately brought an unacceptable overhead to my project. It does not get out of the way as soon as you attempt to use it with the rest of the ecosystem. There belies its arrogance: it treats JavaScript as a second class citizen and favors Typings (additional files that assign types to plain JavaScript libraries). But in most cases, Typings are outdated, or nonexistent. Only recently has support for plain JavaScript libraries gotten better, with the AllowJS and CheckJS flags, the latter of which Visual Studio 2017 does not recognize for whatever reason.

In my view, it comes with so much baggage that it's probably not worth using. Some of the solutions proposed by the project maintainers amount to writing boilerplate just to support JavaScript functions. It's essentially C header files: you have to write module declarations for certain plain JavaScript libraries to work. There are different versions of this boilerplate that you could be asked to write: you may be told to write a typings file (i.e. declare every single function of the library you want to use in a separate file, and add it to the project, possibly using ///<reference> in certain specific scenarios). There are also ad-hoc declarations of modules and constants/globals that you may or may not need to write (there is no idiom here, and the language regards this as going off-road).

I completely agree with this. It's maddening to hear everyone wax lyrical about the benefits of typescript when I see non at all, after you balance the benefits of type safety against all the flaws inherent to typescript itself.

You used the word "arrogance", and that's exactly what it is. The fact that it's a transpiler (and a poor one at that) makes no sense to me. It's reach exceeds it's grasp and it burdens developers with the task of fixing it's own failings.

Before anyone says "you just don't like typed language", stop right there. I do like Typed languages. Typescript is just very very poor when compared to other modern typed languages.

It's such a horrible development experience that I'm looking for a way out of web dev. It's clear the community has gone nuts for it. And the Java back enders who seem to have an unwarranted amount of influence in this world are forcing it onto front end developers simply because it looks like Java. And damn you Angular2 for making all of this worse. You're a clunky and bloated framework already, but not content with ramming your flawed methodology down our throats, you've gone and stuck Typescript in there too, seemingly just out of spite.

I fear Typescript is here to stay. If that's the case, I'm moving to Swift and iOS, or changing career completely.

As someone with 10+ years JS experience and now 3+ months TS I can not agree with you and the gp. It's total hyperbole what you are writing.

We are converting our huge and messy JS code base to TS, which uses a plethora of libs like jquery + plugins, bootstrap, kendo, knockout, and now React (don't ask me, I don't make the decisions), and we are not even close to done yet. So far TS has been a huge productivity boost. Refactoring is a breeze and the compiler found so many subtle bugs that our JS code had. Converting JS to TS is mostly straightforward, just a few type annotations here and there, the compiler can infer types mostly by himself.

Sure, TS has it quirks, the type definitions of external JS libs is not perfect, allowJs can sometimes be a pain, but so far there wasn't really anything as bad as you make it sound. where we would say "screw TS, let's go back to ES/babel". Quite the contrary, none of our JS devs would go back to plain JS. JS is a huge pain in the ass to refactor, especially on large and complex code bases.

> I fear Typescript is here to stay. If that's the case, I'm moving to Swift and iOS, or changing career completely.

Good riddance then, I'd say :) I'm sure Swift or iOS development has no quirks whatsoever.

When the tooling works, it has some really great things mostly related to IDE functionality. But when it doesn't it's a nightmare. It's more than just quirks. It's not hyperbole either, I just had a different experience with it than you.

I sincerely hope it doesn't die on you after you convert your codebase. I wouldn't wish that on anyone.

It's far worse than "the definitions for external JS libs are not perfect;" it's that the TypeScript compiler throws a tantrum when they aren't perfect, which is >50% of the time, to be generous. AllowJS is relatively recent and didn't exist when I started using it - which is shocking, because integration with the JavaScript ecosystem was a major selling point (just check the TS project site's front page). CheckJS is very recent and VS2017 doesn't even support it yet - for a language whose main selling point is tooling support, it's shocking that VS2017 doesn't let users update their TS version.

Another selling point listed on the front page of its website: ES2015 features. Except it doesn't provide Promises, Map, Sets (and I can't remember if they added Object.Assign support, but it also was not supported when I was using it). When you provide your own polyfills, TSC complains unless you provide typings and add specific config values informing it what you polyfilled.

Its 3 main selling points were JavaScript ecosystem integration, ES2015 features, and tight tooling/IDE integration. Each of those things failed me when I used it. The IDE part hurt me the worst, preventing my project from compiling altogether for a while. Every one of its main selling points has been a pain point for me.

> Except it doesn't provide Promises, Map, Sets (and I can't remember if they added Object.Assign support, but it also was not supported when I was using it). When you provide your own polyfills, TSC complains unless you provide typings and add specific config values informing it what you polyfilled.

I think you may have misunderstood what Typescript is and isn't.

It isn't meant to provide polyfills, it is only supposed to handle the grammar of the language that needs to be transpiled.

That's why you have the two following settings: - target : Which version of the grammar will be available at runtime (eg. classes, async, ...), that's the part used by the transpiler - lib : Which libraries (eg. promises, maps, sets, ...) you know will be available at runtime (only used for type-checking)

Using a polyfill is really easy if you are using the right value for "lib" since the it will have the same signature as the real method: simply import it once in your project.

That's fair enough. My actual main issue with this is that TS was hostile towards any external JS libraries, especially before 1.8, but still sporadically in 1.8+, and that affected polyfills too. I also had serious issues importing external libraries that provided their own polyfills.

It was sort of a catch-22 that it didn't like JS yet expected JS polyfills. This has been greatly improved but it took far too long for a project that purports to be a part of the JS ecosystem, which raises questions and I must admit, makes me cynical about whether this was a business tactic.

I've now written many replies with elaborations and clarifications of my criticisms, so it may seem like I'm excessively negative about TS. I actually really like the language itself, especially the static type checking, which is the one main selling point. The OO language features are great because they're optional. I just think everything around the language is rough, and if you're unlucky with it, it can ruin the whole experience.

I remember that at one point, people would declare `require` and use `import whatever = require('whatever')` for npm libraries. This thing was for the longest time absolutely hostile towards JS, and some remnants of that philosophy remain to this day.

I have not forgotten being told to write what amounts to C header files, for JavaScript, in order to allow TSC to play nice with the ecosystem! That was definitely hubris.

> I sincerely hope it doesn't die on you after you convert your codebase. I wouldn't wish that on anyone.

Pretty sure the product I'm working on will die long before TS :) I think TS is here to stay, and if MS decides to drop it, for whatever crazy reason, then the source code is available. And there is still the option to take the compiled JS code, and hope for some "cleanup" tool, like Decaffeinate, or gradually clean it up yourself... Not nice I agree, but I see no dead end here.

> it's that the TypeScript compiler throws a tantrum when they aren't perfect, which is >50% of the time, to be generous.

Really not sure why our experience differs so much from yours. Like I mentioned, we use a shitload of popular libraries, and for every single one there was a d.ts file available. If I see a definition that is wrong/outdated/broken then I create a fork, fix it and make a pull request. Doesn't usually take longer than a few minutes (depending how outdated the definition file is). Instead of complaining, I try to actively help improve the situation. Most of those d.ts files are written by normal developers in their spare time, after all, so it doesn't help to curse those people.

> Another selling point listed on the front page of its website: ES2015 features. Except it doesn't provide Promises, Map, Sets (and I can't remember if they added Object.Assign support, but it also was not supported when I was using it). When you provide your own polyfills, TSC complains unless you provide typings and add specific config values informing it what you polyfilled.

Yeah it's weird, and I don't get it either. Our solution to this is to run the compiled JS code through Babel. We use webpack for this and it's pretty much hassle free. On the other hand, for someone new to TS/JS this may not be obvious. So I agree there is a tooling problem in this regard, but once you know about it, it's a non issue. So yeah, it would've been nice if the TS compiler did properly polyfill things.

And don't get me even started on Visual Studio. I hate to work with it. It's nice for small projects/solutions, but we have a rather big solution, with a couple "Azure cloud classic" projects, and the whole thing is soooo fucking slow. Changing a single value in a ServiceConfiguration.cfg file will freeze VS for almost a minute, for example. There is lag and delays everywhere. The "TypeScript for Visual Studio Extension" was also very problematic, so we disabled all TS features in VS. We use Sublime/VS Code only since a very long time to edit our JS code. VS is a sad joke for a frontend developer.

I'm absolutely fine with external libs not being typechecked if there's no d.ts. The issue is it literally didn't support this scenario until 1.8 (when AllowJS was added). To me, this is the biggest tell that there's something fundamentally wrong with TS's design priorities. How could it not support JavaScript libraries for so long?

Here is one of numerous posts mirroring one of the module resolution issues that has plagued my project: https://stackoverflow.com/questions/39957100/visual-studio-2...

There are equivalent reports on GitHub and elsewhere on the net, as well as numerous related but separate issues.

IDEs from the same organization that sponsors TS don't even work reliably with it. Note one of the responses: "try VSCode." Indeed, VSCode works for me on the exact same code.

Currently I'm doing the same thing as you: running the TS output + the non-TS codebase through a giant blender of browserify + babel.

At one point, I would use --outfile, which makes TSC bundle all your files and dependencies. Neat, right? Nope - it gets the order of the dependencies wrong, which you find out later, at runtime. The maintainers on GitHub said "don't use outfile."

Are you really sure it wasn't possible to use external libs prior to the allowJs flag? I vividly remember a colleague fiddling around with TS when 1.0 was released, and we had discussions about definition files and how lacking they were. But I'm pretty sure he was able to declare an external module as "any" in a d.ts file, and then he could simply require it and use it without type information. As far as I know, the allowJs flag allows you to import/require your own .js files (as opposed to external modules), before that this wasn't possible apparently. Without this functionality I don't know how it was possible to gradually convert a code base to ts. We probably wouldn't be using TS now without the allowJs flag. I guess we are lucky to have picked up TS in a state where most of the early issues have been resolved (not saying there are no issues left).

I totally understand your frustrations with VS, though most of the problems you mentioned seem to be related to the TS integration in VS, and not with TS directly. But issues like yours are the reason why I lost hope in VS. I try to use it as little as possible.

I'm not sure if it was impossible, just that it was a giant mess and it utterly failed to work properly for me. Broadly speaking, point is just that TS treats JS as a second class citizen, and it adversely affects the day to day usability.

it seems reasonable that it didn't allow it before the language designers explicitly created a flag for it.

That doesn't mean some enterprising soul wasn't able to make it work, but it does mean it wasn't officially supported.

Or maybe - and this is what I'm honestly inferring from your comment, it's not snark, it's just a hunch based on 16+ years of web development experience - just maybe there were issues with your teams code quality that means TS has been a huge win for you. Looking at that stack, it seems like someone in your organisation likes sticking plasters over problems.

I'm not a Javascript apologist by any means. I think Typescript makes an already quirky and clunky language worse.

Yep, sticking plasters over problems describes it perfectly ;) Many refactoring attempts, but never completed, because JS makes it really hard. And yes, code quality is bad. Most of it was written by people who never wrote JS/HTML before, then it grew historically and here we are with this mess.

But besides TS being very helpful in a messy code base, personally I would also always start a new project with TS. For me the benefits greatly outweigh the minor annoyances (I really see them as minor)

> Looking at that stack, it seems like someone in your organisation likes sticking plasters over problems.

glad to see I'm not the only one that got that from the post.

Fortunately, ES6 and 7 are very pleasant to work with. And say what you will about Facebook as a company, but their tech side tends to favor lean technologies over bloated ones, e.g. React over Angular (don't get me started on Angular!). I would pursue that path if I were you.

I think the difference comes from the fact that Facebook makes things for the web. Their technologies are born out of necessity. Typescript feels like an academic exercise, created by someone who doesn't like Javascript (and there are good reasons to not like Javascript), and wants to reshape it to there tastes, but in the abstract, outside the context of real word usage.

And Angular feels more like a land grab than a useful tool to me.

If you haven't used it, Flow is a fantastic alternative to TypeScript. They still have some hiccups about working correctly on windows, but it's a much easier way of doing typing in JS than TS.

I've tried flow too. I've got an article on the boil that walks through creating a production ready SPA with Babel, Typescript, and Flow. Covering the whole stack including Webpack, unit tests, and integrating Typescript with Babel (which is still a must as far as I'm concerned).

If I got to make a choice, I'd use tern.

Except it is impossible to prevent it from typechecking node_modules; so if you have a dependency that was checked with a different version of flow than you are using, you may see errors that are impossible to silence.

The only way I've been able to get Flow to be usable on my low-specced laptop is to tell it to [ignore] node_modules/.* and add a file to both [ignore] and [libs] which has one of these for each of my dependencies:

    declare module 'npm-module-name' {  declare var exports: any;  }
I needed similar for TypeScript when trying to use noImplicitAny: false - adding "typeRoots": ["node_modules/@types"] in compilerOptions and a d.ts file with the following listed in "files":

    declare module "*"
Typechecking third-party dependencies seems to be a bit of a crapshoot if you're not in a part of the module ecosystem where the tool you're using is either quasi-required, popular or has module authors using the same tool and shipping type definitions themselves. I've had contributed type definitions in both Flow and TypeScript "break" working, tested code.

Typescript is different - I can use type definitions from NPM without typechecking dependencies I don't import.

Angular initially solved a very small problem - forms. It just scaled really badly (by design but then it was never highlighted in the documentation) and then had second system syndrome

> It's such a horrible development experience that I'm looking for a way out of web dev

Before you abandon web dev altogether, you'd possibly enjoy the React or Vue communities more where TypeScript is not as popular, and Babel (writing ES6/ES2015+) seems to be the default. (e.g. create-react-app and vue-cli's 'vue init' default to using Babel).

I'm a React guy. React + Redux + Reselect + Sagas + Immutable.js is my goto stack. And I like to work with React-Boilerplate when I'm working on something big. But I'm handy enough with Webpack and Babel that I can spin up a small project on my own without needing create-react-app.

But I'm a "consultant". So I have to take the clients desires into consideration too. On my current project, I managed to steer them away form Angular2 (which they'd never used in anger) to React+Redux. But they tacked on Typescript (after rejecting Flow) for reasons that didn't make very much sense to me.

As a result, I've got a working version of what is essentially React-Boilerplate written in Typescript, which I can't share with the community because the client isn't into sharing (but they sure do love using other people's code), but even if I could, I'd be wary of doing it because it would validate what I believe to be a massive mistake.

But the moral of this story is; Often, the decision to use a library, framework, or language is not the developers choice. And it is often a decision taken for questionable reasons.

I've had similar experiences. It's not enough to scare me away from using TS but it comes with a price, and I wouldn't apply it to a project until it reached a certain size.

First off, I really like the language design. It's typing but without the red tape or the ceremony that makes languages like Java so bloated and painful. Duck typing works nicely. Not having to name every little type is a breath of fresh air. Typing is optional and easy to add when needed. It works well with both VSCode and IDEA.

On the flip side, I've found myself spending far too much time trying to find the right typings to match the libraries that I use. It's very easy to end up with odd conflicts. Reminds me of the (hypothetical, of course) experience of finding subtitle files to match a bootleg movie. More often than not, they are off by five seconds, or jump out of sync midway due to been for the director's cut or whatever. Typescript typings are a bit like that; they get you 98% of the way but the last 2% can be surprisingly frustrating. That being said, after it has become possible to install typings from npm, it has become somewhat more manageable.

But yeah, there is a premium to Typescript, like there is to unit tests. It's not a premium that I want to pay for a project unless I'm pretty sure that there is a payoff down the road.

We've found the most productive way to use TypeScript in VS.NET is to configure it as part of your Webpack build where it's bundled along with all your other assets. You can then disable TypeScript errors from breaking your VS.NET builds by adding to .csproj:


When using Webpack you can run `webpack --watch` or run the Webpack dev server where it will instantly process changed TypeScript files to provide an optimal iterative dev work flow:


Good advice, and I'm already doing something like that with a gulp script and Browserify.

The following is specific to my case: as I'm working on a Cordova app, in order to launch the test process, I need VS to think the build was successful, which it often no longer does because TS module resolution and its associated configs are completely erratic. This is VS2015 with its Ripple emulator. I could upgrade to VS2017, which instead uses cordova-simulate, but then other TS-related issues appear. I can go into detail on this if you're interested.

If I set the build flag you mentioned, then it defeats the purpose of TypeScript somewhat, since TS's error reporting being wrong is the reason VS wasn't accepting the builds in the first place. TypeScript without correct IDE integration is nearly useless.

If I move to VSCode, the Cordova extension there decides to overwrite config.xml as it pleases, and you can't debug in Chrome (the extension shuts down if you try!). This bit is not TypeScript's fault, but having to go through all these IDEs is.

To be clear, the above is simply my current problem with TS. My complaints about it are not limited to this one issue I'm facing. It has some pretty fundamental flaws that revolve around its mistreatment of its own JavaScript target.

Just wanted to give a different perspective. Been using typescript for more than 2 years now, on 2 projects of medium sizes (30 to 100Kloc). Those are projects that provide my income, them breaking means no income anymore for me and my associates.

Although Typescript started a bit as you say, complex tooling, had to write external type declaration to have the typing for external libraries (but they are optional, not having them only means not having typing on externals, which is fine in many cases, so not in the way at all), but overall, typing provided so many benefits it was already worth it to me: litterally saved me hundreds of bugs found at compile-time, and keeps the maintenance of the code base cheap and easy. But typescript evolved a lot, now the typing declaration are based on npm, the compiler got faster by an order of magnitude, it provides services to the IDE, and so on.

I just wouldn't start a new project with a reasonable expected lifespan without typescript.

Glad it worked well for you. I really wish it worked for my project, but I experienced issues at every turn and my day-to-day became "the TypeScript show."

>not having them only means not having typing on externals

AllowJS didn't exist until mid-late last year, so using JS libraries was pretty disastrous before that. That definitely fueled a part of my rant. I find this absolutely shocking, for a language that purports to work with JavaScript.

JS modules actually still do not work right for me, as TSC can no longer resolve node modules. I've searched far an wide and found others with the exact same problems and no solutions. It happened suddenly and without cause.

Nor does the IDE integration work for me at all. I've actually done completely fresh installations of the IDEs I've tried but nothing would resolve the issues I faced. I'm stuck with a dud of a VS2015 which can't recognize jQuery from npm. VS2017 can resolve the same modules but fails elsewhere.

It then proceeded to choke on a JS library that uses its own Promise polyfill, yet provided a d.ts file.

No snark, I am genuinely glad it worked well for you. But for me, it's overly laborious getting it to work right, and I've had enough of things like ///<reference> and d.ts files and reconfiguring tsconfig.json.

Maybe Typescript still lacks maturity in the sense that if you can adapt your projects (and your process) to how it was designed to work, then it's great and provides a lot, but on the other hand it may be quite difficult to adapt it to a particular workflow.

I've been using TS pretty heavily now for a few years and I'm pretty happy with it (especially recent versions). I was going to disagree entirely with you, until...

> it has disastrous integration with Visual Studio 2015 and 2017

Yes, this is true. TS, like ES2015+, really wants to have a complete client build system. All the attempts to integrate it into the VS build have been disastrous, from web essentials on down. And you won't learn that from MS. All the problems you mention went away for me as soon as I began to treat the client code as a first-class citizen.

Move all the client code outside the solution and give it its own build, and a lot of these problems go away. I never have problems importing npm modules, and I haven't written a ///<reference> comment in over a year.

> Some of the solutions proposed by the project maintainers amount to writing boilerplate

It sounds like that's a problem with the project maintainers rather than the language.

My first words were that it's a fantastic language. :)

This resonates with me, a lot. Damn. What would you use instead?

Honestly, using ES6+ syntax with Babel and ESLint is a good experience. A comment above recommends Flow for type checking. I haven't tried it so I can't comment.

Static type checking is great in theory but it's just not worth it if you can't get it to play nice with npm modules. I haven't been able to do so reliably in my year of using TS, among other issues. However, don't necessarily take it from me: if you can get it to work, then great, maybe you'll like it more than I did.

If your project has a simple build process, you could still try TS with vscode; it works far better than with VS2015/2017 (that's not to say you won't encounter issues, but it won't be as hellish to diagnose).

Although, IMHO, I would argue that Types just don't fit JavaScript; TypeScript is very OO while JavaScript is not. My TS code is all classes and interfaces. It's quite Javaesque and a departure from the non-TS part of the codebase. It feels a bit too enterprisey and unproductive for the JavaScript ecosystem. This last part is just opinion, though.

This, in addition to the relentless bureaucratic weirdness I encountered, has driven me away. For instance, it doesn't polyfill Promises, Maps, or Sets, even though its front page says it's an ES2015 transpiler. You have to polyfill them yourself, and then you have to get TypeScript not to reject them by providing typings (https://stackoverflow.com/questions/30019542/es6-map-in-type...). You also have to set a config flag in tsconfig.json that tells TypeScript that you're providing those polyfills, i.e. {"lib": [ "es5", "dom", "es2015.promise" ]}. Good luck finding all of this information in one place.

I think TypeScript is secretly the enemy of JavaScript.

as a react/redux developer i tend to write very functional javascript.. We had a CTO try and ram TypeScript into the project and it went over like a fart in church.

Well the point is choice. The more choice the better. I don't personally like intermediate languages. To each his own. I rather write javascript and css rather than get coffeescript or sass involved.

Agreed - CoffeeScript was a great stop gap solution, but with ES6, it seems it's marginal utility is limited.

Well you have to ask for whom. For existing coffee script developers, they can keep using it until they get up to date with ES6. It's a language and it takes time to learn.

I'm not sure I'd agree that there is the concept of a "coffeescript" developer. Coffeescript is an intermediate language in the same way SASS is to CSS.

If you program in SASS and feel out of touch touch with CSS, then I feel you've lost your way. In the same vein, if a CoffeeScript developer, needs "significant" time and investment to transition to ES6, then I would think there is a significant erosion in that developer's understanding of CoffeeScript's ES5 underpinnings.

Yeah you are right. I was making a general point in the case of coffee script perhaps it's irrelevant. I don't write it so I am not in the know.

Except sass is a fully backwards compatible superset to CSS, and coffescript is definitely not that to JavaScript.

Really? Are you sure? If CoffeeScript isn't fully compatible with JS then what is it? I mean at some point it has to go through a JS interpreter to run.

I created a coffee file called list.coffee with:

    var list = [1, 2, 3, 4, 5];
When I run `coffee list.coffee` I get:

    /home/****/Code/coffee/thing.coffee:1:1: error: reserved word 'var'
    var list = [1, 2, 3, 4, 5];
The coffeescript interpreter is standalone and does not turn it in to JS.

there are clear value adds to sass i find.. not so much w/ coffeescript..

sass is more than just syntax sugar.

>I don't understand the trend to move from Coffeescript to ES6.

ES6 is supported natively, it's an actual standard not a language a single person came with, it avoids a build step, it has all of Coffeescript features and more by this point, and Coffeescript's momentum has slowed. Seems a no-brainer.

And as for concision, ES6 seems just as concise. At worse you need an extra } or so, which I like to have anyway.

> it has all of Coffeescript features and more

No! It seems you've never learned Coffeescript well enough to know the differences, just like too many other ES6 proponents.

I learned Coffeescript well enough to not care for the differences.

There's nothing especially interesting Coffeescript has over ES6/7.

I miss the existential operator like the deserts miss the rain


Truly. That operator has most of the gravity that pulls me towards coffeescript.

Lodash things, like _.isNil staunch the bleeding, but it's just.. not the same.

I wrote coffeescript for 3 years, and the first 2 or 3 months was a frustrating learning curve. By the end of that job I really drank the koolaid. Coffeescript can be blissful. The complaints about invisible delimiters and stuff resonated with me for the first 2 weeks, but then I just learned it like you learn anything. If you are unsure what's going to happen, add extra parenthesis. I kept a window with js2.coffee on it so I could paste uncanny snippets while I was getting up to speed. After I got over the curve I stopped needing it.

I think it was more frustrating in the beginning than learning most things because I knew JS pretty well prior and it felt like I was throwing my experience out the window. I'm glad I did it though. Writing coffeescript was really quite pleasant. Now regular javascript has jumped forward a bit and has somethings coffeescript doesn't, I still feel like the one true web language exists somewhere between them.

I'm leading a project right now and every couple of days I get that coffeescript itch. Caffeine is hard to put down once you're addicted.

Just found this. https://github.com/rongierlach/babel-plugin-syntax-exists not the worst workaround in the short term. Better than lodash's _.get but worse than coffeescript. :P

Mixed feelings about CoffeeScript, as ever.

ES6 obviously deals with some of the issues that CoffeeScript was intended do. That's awesome. Unfortunately, it's still difficult to go back to what seems like the relatively baroque syntax of Javascript afterwards, as someone who has a bit of a vendetta against over-syntax. SO MANY BRACKETS.

In particular, there was CJSX - JSX with CoffeeScript. Writing React components using it was an absolute joy in comparison, and helped eliminate a lot of noise – making it much more obvious what a component was doing.

But yeah, it's been hard to convince others that it's worth the investment, when honestly it's really just a personal preference at this stage.


Whatever do you mean?

Promises returning promises (or async/await which is just sugar-coating for promises) solves this very cleanly in my experience

I agree. Promises have solved most our team's nesting issues.

It's incredibly clear, allows clean and concise error handling, and is easy to use.

the text editors/ides I use today have bracket matching and with eslint it's been easier to track missing/extra bracket bugs, the example you have is heavily exaggerated, nesting like that is bad code with or without brackets

It is still confusing. Look at how clear python files are for example.

My editor's colorscheme makes brackets dark gray and I don't use semicolons in JS because it's optional. It's really not that ugly. I What IS ugly is inspecting machine generated Coffeescript source code in Chrome dev tools and debugging it.

So is having to set up preprocessors whenever you want to use Coffeescript. Which is easy in Rails but a challenge in many other scenarios such as simple static sites.

Not to mention the number of projects I've joined which has a random mix of both .js and .coffee files.

I'd prefer spacing over bracket if it was natively supported in the language as it is in my favourite languages Erlang, Elixir, and Haskell. But that's not the case here.

CoffeeScript 2 will compile classes to ES6 classes, among other changes. So the output should be more readable than it was previously.

Exactly, which sort of mutes the effectiveness of this tool. Coffeesctipt 2 is already a coffee to es6 transpiler

Python would be even worse in this situation, IMO. At least brackets are visible; having to line up a bunch of indentation for that kind of nesting depth is the sort of thing that gives me nightmares at night.

Didn't ES6 promise ;) to solve this?

I'm awaiting ES7 :D for the true solution to this problem. It'll eliminate the boilerplate of .then(function() {})` entirely. Less brackets, less ceremony.

ES7 was finalized a year ago. Everything except IE 11 supports all of it.

You meant ES2017.


And all current browsers save IE11 support ES2017 async functions.

Isn't ES6 `.then(()=>{})` ?

Or even without curly braces:

`.then(x => doSomethingWith(x));`

This is true only insofar as libraries use promises, and your code uses promises. They're still pretty annoying in my experience.

There are still some other cases where the mess of brackets is overkill, other than callback hell.

> This is true only insofar as libraries use promises, and your code uses promises. They're still pretty annoying in my experience.

Promisify, or (as I prefer to) just "return new Promise((resolve, reject) => { nonPromisedStuff(...) })"?

> There are still some other cases where the mess of brackets is overkill, other than callback hell.

Like bad coding style?

Who writes JS like this?

This is something I'm left wondering. I've written a lot of JS, some of it in complex applications. I've never had this issue of mass nesting that would cause all of these brackets people here seem to be complaining about. I'd suggest that coffeescript isn't solving issues with javascript syntax, but instead is allowing the kind of code that should be refactored out to stay around for longer as it doesn't look so ugly. That's not really a good thing. Perhaps it's a good thing if the community lets it die.

You might not feel like you wrote too many brackets, but good luck convincing someone who uses none (except for hashes) that they should start. Coffeescript code is not sloppier, its more terse.

People who have not yet discovered named functions.

It takes time to get those brackets right; time that adds up. That's one of the many ways CoffeeScript contributed to my own productivity over the years

Only if you're editing text with a potatoe.

Assuming you have an editor which auto wraps pararenthesis then with Coffeescript you are basically exchanging brackets for spacing with zero productivity gain, besides some features such as list comprehension and easier handling of that = this.

Additionally every JS file has to be preprocessed making debugging slightly harder and set up more involved. Every person contributing to the project has to become familiar with CS. Plus mixing both CS and non-CS files always ends up happening in my experience.

As a former CS fan, I really don't see the utility of using CS like I used to.

So we're assuming that everyone only ever writes new code in a situation where auto insertion of parentheses would kick in and contribute. Don't you people have to edit existing code? Callback hell anyone?

If you're using ES6, you're already likely doing a compilation step anyway. So I'm not too sure there's much loss.

True, I've been using Babel for ES6 when not working on chrome extensions or sites limited to early adopters which I look forward to not having to depend on. For Node you don't need Babel to use ES6 besides support for import instead of require.

I still find having to use Babel annoying.

I built LightScript because of this; you might give it a try.

It's a rough superset of ES7+JSX+Flow, built on Babel. Integrates pretty well with a bunch of tools like ESLint, should be much more future-proof than coffeescript.

Would love your thoughts if you'd like to give it a try - http://lightscript.org

That actually looks lovely I'll check it out!

Thanks! Happy to help in the gitter chat if you have any questions - gitter.im/LightScript/Lobby

I really appreciate the thin arrow syntax.

I've work for over a year on a CS codebase and, while brackets are ugly, but I'll take visible ones over invisible ones any day.

100%. I think CoffeeScript put the cart before the horse by promising some nearly-magical block detection and then they were stuck trying to implement it. I find that CS code is very temperamental and difficult to maintain over the long term.

"No brackets, it's so pretty!" is fine, but other languages don't make what feel like random guesses as to where your delimiters are, they use a different syntax to mark the blocks.

Personally I prefer to just mark the blocks myself rather than hope that the compiler infers it correctly, whether that's done with indentation as in Python, keywords like "begin" and "end", or with C-style bracketing. I even find comparatively mild things like Ruby's inferred parentheses grating.

There's no reason not to put an opening and closing mark. You're already thinking in delimited terms when you're writing the code, there is no real extra cost to throwing in the indicators, and it makes it so much easier to figure out what's going on when you go back to debug, when you try to read the code after months, or when your text editor is trying to help you out with folding and the like.

Whether or not bracket free code is more readible might be a personal opinion. I think for people who understand Coffeesctipt well, its easier because theres less visual noise. There are many languages with optional parens, and whether or not you want to stretch the ability of the parser is up to you. Coffeescript proves that they are not necessary in order to write javascript.

> I even find comparatively mild things like Ruby's inferred parentheses grating.

I agree with everything you've written and I'd like to note that even Ruby has degenerate cases where you're forced to use parenthesis around things because the parser can't figure out what you mean.

I have an instant dislike for any language that tries hard to make code 'pretty' by removing such indicators.

And to be clear, there's a difference between a concise version of a syntax, such as C#'s lambda syntax, and creating inconsistencies in your language by trying to remove syntax that cannot be universally removed without creating ambiguities.

The former is welcome, the latter is not. Even Ruby has such degenerate cases.

And I like Ruby, but I dislike that design decision.

Yeah, I think that people jump on that bandwagon just assuming that it will work magically. It is better to explicit about it if the cost is minimal. Python also strove to eliminate unsightly bracketing, but it did so by replacing the characters with a more readable delimiter, not removing them entirely.

To be fair to Ruby, most of the time when I've come across a situation where the call became ambiguous due to lack of parenthesis, the failure was obvious and easy to fix. I still think introducing that type of ambiguity into the language is an antifeature, but compared to CoffeeScript, where the automatic delimiting is non-intuitive enough that you often have to compile it down to JS to check that it's rolling everything into the right place, it's no contest.

On our CoffeeScript project, the compiled blocks would change layout even with very minor changes to spacing or code arrangement. It would've been much easier just to throw in a () and tell it what we meant!

I'm not saying it's insurmountable, but the gain just isn't worth the cost imo.

So, what you are saying is that you don't like language that have operator precedence rules so that you can omit some uses of grouping parentheses in expressions? Because that's the same level of inconsistency due to non-universal removing of markers as Ruby's permitting function-call parens to be removed when unambiguous.

What I'm saying is that anyone who's judgement is so poor as to try and argue operator precedence in this discussion isn't worth bothering with.

> I have an instant dislike for any language that tries hard to make code 'pretty' by removing such indicators.

Ah, you see, I don't, or didn't :)

I thought bracketless code would be magical, until I had to wander through nested callbacks with implicit returns.

I've found that writing React render methods in plain CoffeeScript is actually pretty pleasant, too. I gave it a try not long ago and it came out looking pretty similar to Elm.

Yeah, I can see that. There are a few things that make it nice, like the `@` sign in place of `this, and implicit returns (which remove a bunch of boilerplate and brackets).

> just a personal preference

How does one objectively measure this? I strongly prefer to read less code, to make fewer mistakes (I.e. closing brackets).

I love CS and I see myself using it for another 5 years. The aversion developers have had to CS never were legit reasons. If you put all your time in ES6 and CS, I think you'll be more productive in CS.

The only issue I foresee is tools being built around the use of ES6 that compel you to abandon it.

I've learned that less is better. I don't use JQuery, I don't use Lodash. I don't use React, I don't use ImmutableJs, I don't use Webpack or CommonJS. All of these tools are more a burden that a blessing and you just end up stacking on 100 dependieces asking "Is this really better?"

I learned this lesson with Cucumber/RSpec/Caybara and etc.. I started asking why I had to use these over plain old TDD and so I used TDD for a month and I found out everything was totally fine.

I don't even really use Arel in ActiveRecord. I just write raw SQL that serves JSON directly back. I made it easier for me to organize SQL in partials just like views and to injects variables and conditions into my SQL.

I went to great lengths to evaluate all these tools because as a work-form home contractor I can afford the time, and the "what if" really bothers me.

I still working in Rails with Sprockets and CS and I write all my SQL by hand.

Less is Better.

All these kids want to do a bunch of busy work and for no good reason. It makes the feel productive.

I have tried dropping CS but the difference in productive was too great to drop. Its not that I'm married to CS its that it does what it says. It makes your JS concise so you can be more productive.

I felt AngularJS dying and so I spent 3 months researching React and building client apps in React. I just didn't get all the work extra work and settled on Mithril.

The hardest thing was giving up writing HTML-like templates like I did in AngularJS but I remember that was my first aversion to AngularJS where I swallowed the medicine. I had to swallow more medicine to unlearn that. Mithril paird with CoffeScript makes writing markup in CS a joy. If I had to do that in regular JS I could see why people would be compelled to use ugly JSX.

> All these kids want to do a bunch of busy work and for no good reason. It makes the feel productive.

This is pretty patronizing. Not everybody who uses these tools are "kids who just want to do busy work". In fact, I'd argue that "kids" (or more accurately, "new developers") are the least likely to want to do busy work, as they'd prefer to be able to build stuff fast. (And for the record, I feel like I suddenly started doing a whole lot LESS busy work once I got decent with React.)

I generally agree that "less is better", until you have to start re-inventing solved problems.

> I learned this lesson with Cucumber/RSpec/Caybara and etc.. I started asking why I had to use these over plain old TDD and so I used TDD for a month and I found out everything was totally fine.

RSpec is just a testing framework though? It's not something you chose instead of TDD...

>I generally agree that "less is better", until you have to start re-inventing solved problems.

I think the takeaway is that before you assume you have an "unsolved problem" due to all the buzz/hype around $HOT_LIB, study a little more, try it with the upstream, make sure it's really necessary before you get a tortured contrivance of a stack in place. Consider the cost of adding more dependencies and whether the functionality you're getting from the third party lib is really worth it.

Let's be honest, the core problems you're likely to run into on any given day are probably "solved" pretty reasonably by any language that's at the appropriate level for the problem space and has seen significant use over the last 10 years. You're more likely to be reinventing the wheel by pulling in $COOL_GITHUB_PROJECT than you are by taking a few more lines to implement with the stdlib.

> "kids" (or more accurately, "new developers") are the least likely to want to do busy work, as they'd prefer to be able to build stuff fast

You're grossly underestimating the proportion of new entrant workers in the ICT industry that don't have an aptitude for programming, and cover their tracks by appearing to be productive.

This is /r/iamverysmart/ material.

I'm going to go out on a limb here and guess that you don't work in a large team with other developers, maintaining a common codebase.


I am pretty sure this is the case. I have worked with small and large teams. Large teams usually have a lot more abstraction in terms of their architecture. So there is most likely a "backend" app that is just an API and you consume it in your "frontend" (node, rails, etc) whatever that may be.

Frontend in this context is just another server that is communicating with backend APIs using RPC. When small teams think of frontend, they usually think about a framework like React, etc and pair it with a backend like Rails.

CoffeeScript is ES6+ with a bit more expression-ness, less punctuation, and fewer new features like async/await. CoffeeScript's grammar and compiler have always been a bug-ridden mess (a fix was my first open source contribution), while for ES6+ you have three different well-supported sanely-engineered cross-compilers, as well as native support in browsers, and support from every development tool made in the last few years.

I loved CoffeeScript in 2012, but even then it was clearly a stop-gap, and we're on the other side. You're putting yourself at a strict engineering and hiring disadvantage, in return for... having less punctuation so you feel better about writing markup in your JavaScript..?

> I don't even really use Arel in ActiveRecord. I just write raw SQL that serves JSON directly back. I made it easier for me to organize SQL in partials just like views and to injects variables and conditions into my SQL.

This seems misguided. Arel is already very much like a library for partials for SQL that allows composition and takes care of tedious but important concerns like injection safety.

> All these kids want to do a bunch of busy work and for no good reason.

That's what your SQL-partials system sounds like to me! Different strokes for different folks.

I think that Tom Dale made a pretty good argument of why to avoid CoffeeScript as part of his argument for TypeScript.

"For example, CoffeeScript adopted for..of loops to iterate over the properties of an object. Meanwhile, ES6 introduced its own for..of loops as a way to loop through iterable objects. If CoffeeScript wants to support new functionality with similar syntax like this, it has two choices: break existing CoffeeScript code, or diverge from JavaScript more and more over time."


I don't think JSX is ugly. React/JSX are incredibly simple and follow the less is more philosophy.

I couldn't tell if this post was sarcastic or not at first. Seems weird to say Less is Better, and then say you like CoffeeScript which adds a whole layer of abstraction over JS.

I think it really depends on what type of code you write. In many many cases, the code you write in CS is exactly the same you would write in JS. The difference is that you can omit some elements that visually clutter the code like brackets

Thanks for the pointer to Mithril. Hadn't heard of it.

> The only issue I foresee is tools being built around the use of ES6 that compel you to abandon it.

A friendly CS fanboy here. With CS2 many tools become trivial to integrate and work with

"I just write raw SQL that serves JSON directly back."

I'm surprised and intrigued by this. How do you get your query to return JSON? What percentage of your code actually works like that? How business logic heavy is your SQL? This is super interesting!

I've also managed to obtain extremely good performance from this approach. It's good in areas where for one reason or another you need to dump several MB of JSON, which languanges like ruby simply can't do performantly but postgres definitely can. Here's an extremely quick and dirty example:

    def serialize_in_postgres(relation, columns)
          select array_to_json(array_agg(row_to_json(result))) from
          ( #{relation.select(columns).to_sql} ) result

    puts serialize_in_postgres(SomeArModel.limit(2), ['id', '"created_at"::date'])
    # => [{"id":12345,"created_at":"2017-06-11"},{"id":23456,"created_at":"2017-06-11"}]
Unlike the parent, I would not recommend doing this everywhere, or even most places, but it is a very useful tool to have.

Postgres and probably others support JSON these days.

Shameful plug: http://invig.io is a a wrapper around decaffinate, lebab, prettier, eslint, to to squeeze more modernness out of legacy js/coffeescript codebases and make them standardjs.com compliant

That sounds excellent (especially if it supports await!). Slightly off-topic:

I love standardjs.com. It takes an enormous amount of chutzpah to look at jQuery style guidelines, idiomatic.js, AirBnB and every previous JavaScript style guide and declare the name of your own new thing is `${standard} ${languageName}`

"Standard" (the name is very hard to tolerate) not being configurable with questionable defaults (no semicolons!) and being JS-only (no TS or CSS support) makes Prettier[1] a better option. It has a VS Code extension which works great.

[1]: https://github.com/prettier/prettier

> Prettier parses your JavaScript into an AST (Abstract Syntax Tree) and pretty-prints the AST, completely ignoring any of the original formatting*. Say hello to completely consistent syntax!

That's excellent. Thanks for the recommendation.

Cool, I hadn't seen that! bulk-decaffeinate is a wrapper around decaffeinate, jscodeshift, and eslint with a similar goal. And I've certainly thought about incorporating lebab and/or prettier there as well.


CoffeeScript has some nice feature, especially as compared to ES5, but I always found it a tad too clever. The fact that {} are optional in a bunch of places makes it very difficult for me to parse mentally.

Other weird coffeescript quirk: "x isnt y" is not semantically to "x is not y".

People overuse {}-free object literals in CoffeeScript. In function invocations, and other in-line cases, use {}!

Oh thank god.

CoffeeScript was an important crutch and stepping stone but we're maybe 2 years past where it has been past it's prime and this will make updating and improving legacy projects a lot easier.

Personally was never a fan of it - it used too many Ruby idioms for my taste and produced noisy code that was a pain to debug (at the time) - but it did spur the development & adoption of other, better, systems (ESNext transpilation, TypeScript, etc)

I did an experiment about a year ago when I re-wrote part of LiveScript's code emitter to produce a babel-compatible AST rather than javascript code. It would then pipe the AST to babel's generator and produce the final JavaScript. The benefit was that I could then use any babel-compatible toolset and still write code in LiveScript. ESLint worked with almost no tweaks necessary. Theoretically, you could also use Flow and TypeScript with this approach.

Anyway, I didn't have enough time to finish the project, but somebody took the idea and did most of the work [0].

[0] https://github.com/dk00/livescript-next

Would love to explain more, but have to board the plain now :) These links might help:

https://github.com/gkz/LiveScript/issues/821 https://github.com/facebook/flow/issues/1515

This thing made me use React in 2013 (when JSX was still weird): http://blog.vjeux.com/2013/javascript/react-coffeescript.htm...

Now JSX is not weird anymore, it's just horrible.

The folks behind this have been at it a long time. I first used decaffeinate over 18mo ago and while it was already quite helpful then, it's come a tremendous distance since. Very tricky problem to solve well; bravo!

Somewhat surprised nobody has mentioned the upcoming release of CoffeeScript 2.0, which outputs ES6 natively: http://coffeescript.org/v2/

It's​ in beta2 now and ready for trial.

Never understood the appeal of CS, JavaScript just isn't painful enough to warrant it. Been happy to watch it's slow exit from the mainstream.


Meaningful indentation. I love python and I'm really not sure why other compilers/interpreters ignore indentation since it's the de facto way of how people express structure in any computer language.

Also when CS happened, JS didn't even have classes. Half of the ES6 features are CS inspired.

> Also when CS happened, JS didn't even have classes.

And it only has class syntax now. Classes in JS are still prototypical inheritance under the hood (and probably always will be).

> Half of the ES6 features are CS inspired.

This is rewriting history. Most of ES6 was under active development before CS was a thing. It's more accurate to say that the same modern languages features inspired both (with ES6 thankfully being less Ruby-like).

CoffeeScript is still relevant to me, mainly because of the sparser syntax. For React, I wrap the components in functions to create syntax that is even a little clearer than JSX, but still valid CoffeeScript.

I am still waiting for someone to finish a Python bytecode VM or transpiler for javascript which is actually worth using...

> waiting for someone to finish a Python bytecode VM or transpiler for javascript which is actually worth using...

What is that? Running JS in a python VM?

No, by that I mean a VM to run Python bytecode, running in the browser. There is at least one project which tries to do that, but it's not really useable.

The point would be to have access to a large part of the standard library, the full Python data model and a good integration with the javascript platform. Only then would there be a reason to use it.

Oh. Now I get your point.

Oh how the tables have turned

I'm assuming "modern JavaScript" means ES6. Has anyone used this, and does it produce readable code?

Yeah, "modern JS" is meant to be the catch-all term for ES6/ES7/ES2015/ES2016/ES2017. In this case, you need ES2016 to run code produced by decaffeinate, but anything in the latest language version or at stage 4 is fair game and might be added in the future.

Producing readable code is certainly the intent! Realistically, you need to clean some things up by hand to make it pass lint and look nice, but I think overall it does a pretty good job, certainly much better than the CoffeeScript compiler. You can always play around with it by typing/pasting code into the online repl: http://decaffeinate-project.org/repl/

You mean only ES2016 from that list?

> Producing readable code is certainly the intent!

This is hilarious! Transpiling from the most readable JS alternative to ES6? Then you need to clean up some things, making it ready for yet another transpiler called Babel? And then everything is OK?

Show me how you are going to make this pretty:

  if does.that?.prop?.exist then console.log 'yes, no crash!'

> You mean only ES2016 from that list?

No, I was intentional about my description. People tend to be informal when talking about JS versions, and all five of those terms might be used to describe decaffeinate's output. IMO it's best to just say that decaffeinate produces JavaScript, and not any particular old version of JavaScript.

> Show me how you are going to make this pretty

Soak operations (anything with a question mark) are probably the hardest to convert to JavaScript, especially when they're chained. Here's what decaffeinate gives today:


And here's an open bug with thoughts on making those look better: https://github.com/decaffeinate/decaffeinate/issues/336

But many people have still found decaffeinate useful since the vast majority of real-world CoffeeScript (at least from what I've seen) tends to convert pretty well, and even in difficult cases, it's better to safely get it in JavaScript first and then clean it up than to rewrite everything by hand.

  if (__guard__(does.that != null ? does.that.prop : undefined, x => x.exist)) { console.log('yes, no crash!'); }
  function __guard__(value, transform) {
    return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined;
oh my..

This was 1 line of CS, how to clean this up without a chance of creating bugs?

How on earth is ESxxx an improvement on CS anyways? It's just not true, it's a leap back.

It produces Javascript, so by definition it cannot produce readable code.

It's going to be very interesting to see if Atom decides to fully make the move to JavaScript / ES6+

They're already using JavaScript for all new code, and gradually converting their existing code over using decaffeinate (e.g. https://github.com/atom/atom/commit/30cd83f7aa03c023e6103b64... ). But it's a reasonably big codebase and I imagine moving everything over incrementally will take a while.

What about moving to web assembly? Would it be relevant? Or is this a Firefox feature only? Or is this not interesting because the point is to write it in javascript?

There was actually a huge consensus on the direction of Web Assembly recently. https://medium.com/@treyhuffine/coding-news-monthly-summary-...

WebAssembly will be supported by all browsers and JS engines, but it's not something you would use as your source code. I think at the moment it's more focused on high-performance use cases, e.g. rewriting a CPU-intensive function in C++, compiling it to WebAssembly, and calling it from your JS code. Or taking an existing C++ codebase and running it on the web without really using the DOM. But in the long run, I think WebAssembly will make it possible to do things like DOM interactions in other programming languages.

CS is one of the main reasons I haven't contributed more to Atom.

I guess when Atom was started it made sense to use CS, not anymore. Hopefully Github will switch to ES6/7 or TS.

also this

Instead of wanting projects to move to a language you know, you can better first learn the language they are written in, and try to understand their decision in the first place. If you know CS very well you would not be so eager to move to Babel transpiler imao.

There is also a nice comment in here about a large project that became a misery because of TS. Think twice before you hope!

They're going to have to support it in perpetuity, most likely. There are too many packages written in CS, which are relied on, and which are not really maintained so much.


Wasn't JA updating CS again recently? Has anybody tried to use it after using ES6/7?

Yep, the CoffeeScript folks are working on CoffeeScript 2 (I think JA is participating in some discussions but not actively working on it himself). It's not released officially, but there's a beta, and lots of discussions here: https://github.com/coffeescript6/discuss

I've used the CS2 beta and I love it. Now tons of ES6 tools work like a charm.

Hasn't the community (finally) learned that simply transposing a better syntax onto JavaScript does not solve or help programmers in a meaningful way like the way that static typing does? Or is me hoping that a community will collectively reach a realization like this a pipe dream?

Patronizing? I've mostly switched to TypeScript from CoffeeScript for the time being, because types are indeed a huge boon, but a better syntax is meaningfully helpful and my preference any day would be for some merger into typed CoffeeScript.

Yeah, I guess TypedCoffeeScript would be better than just one or the other.

For what it's worth, I've found that F# has a similar 'feel' to what I'd expect from a typed CoffeeScript. I'm not sure exactly why; it's probably just the look and shape of the code, along with the lack of brackets.

Writing React apps in F# using Fable is pretty nice, too.

Elm is nice. Typescript is okay. Heck, you can even Java if that floats your boat. And with WebAssembly…

If you don't like the language, but have to use it, use it as compiler target, simple as that.

These are not mutually exclusive. We can:

- Support strong typing

- Eliminate redundant tokens

At the same time.

They aren't, but there's no well supported js transpiling language that does both.

how is this different than running the compiled CS output through lebab [1]?

[1] https://github.com/lebab/lebab

You lose a lot of information going from CS -> ES5 -> ES6, so decaffeinate has an inherent advantage since it knows your original code. With decaffeinate, it converts classes to classes, destructures to destructures, array spread to array spread, etc. Also, the CS output destroys all inline comments and all formatting.

In 3-5 years will we get "FreeRange" to convert typescript to "modern" JavaScript?

I love this. We've truly come full circle. Does it support a compile to Typescript step?

bulk-decaffeinate ( https://github.com/decaffeinate/bulk-decaffeinate ) supports an outputFileExtension option that can make it so the resulting files end in .ts. But really, the main thing to do when converting JavaScript to TypeScript is adding types, which decaffeinate is much less qualified to do. But if you're going to move from CoffeeScript to TypeScript, JavaScript is probably a pretty important intermediate step.

Remember when CoffeeScript was "modern JS"?

The whole JS stack switches every 2 years or so?

I mean, it actually switches faster than that and that's what everyone jokes about (JavaScript fatigue and what not). But a full turnover of the stack is about 2 years?

People might not know but CoffeeScript 2 is out already and supports the ES6 syntaxes. I've been using it for a large Vue.js SPA (with webpack) and some small projects, it really improves the development and saving me a lot of the time.


Last time I tried it did not support cjsx -> jsx, as far as I can tell, so it's useless for migrating React code bases.

Take a look at depercolator, it's a wrapper around cjsx-transform, decaffeinate, and some other things:


There's an open decaffeinate bug for CJSX ( https://github.com/decaffeinate/decaffeinate/issues/1009 ) but I suspect it'll be really hard to do anything better than just running cjsx-transform and then running regular decaffeinate.

To get JSX on the JS side after decaffeinate, you can use the create-element-to-jsx script from https://github.com/reactjs/react-codemod .

This is great. I had a hard time dealing with CoffeeScript code. CoffeeScript tools are behind the state of the art in JavaScript.

This is a cautionary tale for developers that flock to the flavor-of-the-month tech (CoffeeScript used to be all the rage in 2013!), only to find that the mature tech not only caught up but completely eclipsed it in 2017.

‎Jeremy Ashkenas (author of coffeescript) helped bring es6 up to par. You can see the influence of coffeescript all over es6 in the class syntax, string interpolation and destructuring.

It would be wrong to say that the investment we (as an industry) made in coffeescript was a waste. Far from it.

> ‎Jeremy Ashkenas (author of coffeescript) helped bring es6 up to par.

By spending basically the entire runup to it poo-pooing it?

> You can see the influence of coffeescript all over es6 in the class syntax, string interpolation and destructuring.

Yeah it couldn't be the dozens of languages which have been doing that since the 80s and which browser developers were already mining for extensions no sir, Coffeescript invented having a class keyword (which is why it was already a reserved keyword in JS), invented string interpolation which it lifted directly from Ruby (according to its own doc) and from which JS string templates diverge both syntactically and semantically, and invented destructuring (and will I'm sure soon invent pattern matching).

Well, in justice, CoffeeScript did influence JavaScript. However some of the decisions were in my opinion bad: removing delimiters and making whitespace more "meaningful". That makes it really hard to automatically format code in a way that deterministically doesn't break.

IMO that was one bad decision in CS1 that they allowed mixed whitespace to compile in the first place. CoffeScipt 2 (which is ES6 compliant) doesn't allow you to compile/transpile any code with mixed indentation.

BTW in Atom, I've successfully used atom-beautify with coffee-fmt and coffee-formatter to reformat very bad code with no errors

The formatter from IntelliJ would cause the file to not compile at times. Maybe I should have tried Atom. Too late now.

4 years is hardly "flavor of the month" - ES4 is as foreign to ES2017 as Coffeescript is.

Can you give an example of a CoffeeScript file being transcribed to modern JS :)? I just want to see which syntax I prefer.

Sure, here's src/main-process/atom-protocol-handler.coffee from the atom codebase (it's a really long URL because it includes the whole source code):


In this case, the __guardMethod__ usages should probably be rewritten by hand after running decaffeinate.

In general, you can paste any code into the left side of http://decaffeinate-project.org/repl to get output on the right side.

Doesn't Coffeescript convert Coffeescript to JS? `coffee -c input.coffee`.

Yes, but it's not "modern JS" and it's not meant to be edited.

This tool converts it to modern JS (ES6) that has classes, template strings, etc.


We detached this subthread from https://news.ycombinator.com/item?id=14585740 and marked it off-topic.

Not sure what the weird hostility is all about, but... I think what they meant is that CoffeeScript doesn't support explicit variable declarations, instead implicitly defining variables when they are first referenced. That makes it hard to add explicit type declarations, because you've got nowhere to declare them.

Yes that's exactly the point I was making.

Adding types atop something like that would be particularly difficult though not impossible. The hardest part is doing something that maintains the magic of picking the proper scope to define a var at without adding "var" declarations.

Sorry, no weird hostility, just an observation. The weirdness comes more from the way how you guys think about creating a typed language. What the heck would a CS compiler with static type checking have to do with var statements apart from generating them in the final JS as it does now already?

Well, in TypeScript you attach the type declaration to the variable declaration:

    let foo: number;
It's true that you could add the type declaration to the first assignment of the variable, as in:

    foo: number = 42
...but that's kind of awkward, because CoffeeScript only has an assignment expression and not a variable declaration statement. You can hack the two together but it's going to make things confusing and complex for the compiler to implement. What happens if you do this:

    foo = 42
    ... 30 lines later ...
    foo: string = "hello"
They're both just assignment expressions, but now they can carry extra metadata about the variable that's being assigned, so there's all sorts of cases you have to consider.

Anyways, I was just trying to clarify what the comment you replied to meant. IMO, the real problem is that TypeScript's type system is incredibly powerful, and a huge portion of the compiler is devoted to static checking for it.

Even if the CoffeeScript compiler could support types, it makes very little sense to spend the effort when TypeScript already exists. The syntactic difference between the two languages is too small. I could see an option for CoffeeScript to target TypeScript as a transpilation output, but then you'd lose the tooling (tslint) built for TypeScript.

And again, why? If you want types, write TypeScript. That's what it's there for.

If you don't have var statements then you lose the number one place to specify the type of the variable.

It's not about making whatever inferences you can from the code, it's about giving the compiler/typechecker the detail it needs to make more accurate inferences.

coffeescript is best for doing a specific thing on a page. for spa it's different.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact