Babel and TypeScript are the main contenders in the world of light JavaScript transpilers, and even though there are some other viable options to transpile/compile your JavaScript from ES6/ES7 to whatever your browser supports, i would say that Babel and TypeScript are the best options you have.

CoffeeScript is also one of the good alternatives, and it is worth mentioning, but it is not what i call a light JS transpiler, since it promotes a syntax that differs significantly from the EcmaScript standard (e.g. using the function keyword throws a compiling error). However Ruby and Python developers usually prefer CoffeeScript over other options.

What is a transpiler anyway?

Well, a transpiler is a tool that takes source code written in one language and transforms it into a language that has a similar level of abstraction.

However, a transpiler is still a kind of compiler, but a very specialized one, targeting a similar programming language as output, so IMHO Babel and TypeScript should be considered transpilers, even though they like to brag about being compilers.

Babel and TS are time-travel machines

Why wait for a new version of JavaScript to be supported by browsers and node.js? Using a transpiler is a pretty smart way to use a future version of JavaScript right now very safely, which is a good thing in my book.

However, Babel is a much safer option, since it follows the actual EcmaScript specifications, without additions (except the ability to enable experimental features). TypeScript on the other end adds additional stuff on top of EcmaScript official specs (e.g. Types and Generics to name a few) out of the box, which many could consider a good thing, but definitely out of the standard.

I like optional types, and there are ways to use them in Babel too.

Comparing transpiled output

Babel and TypeScript both use a similar approach to transpiling in many areas, but the output they generate is significantly different. Let's take a simple ES6 class and see what the output looks like.

So, let's take a look at TypeScript output first:

The output is very clean, old-fashioned with a nice IIFE and using prototypes. Arguably most JS developers would write a class this way.

Let's take a look at Babel output:

The Babel output is also an IIFE, but it uses a substantially different approach by using a helper method to create a class which interally uses more modern features of ES5 (e.g. Object.defineProperty etc.).

TypeScript just has a different transpilation philosophy, which is more targeting support (back to ES3 by default) and readability.

"The goal of TypeScript's translation is to emit exactly what a programmer would type when implementing a class or namespace unaided by a tool." - TypeScript spec

Many consider Babel output to be more complex, but again it is very subjective, and some people could consider the complexity a non-issue since Babel is using more robust features of ES5 by default, while TypeScript is going after simpler, readable output, and backward compatibility (ES3 by default).

TypeScript can also be executed with compiler flags to emit a more modern output that utilizes newer ES5 features.

In any case you will have a hard time debugging transpiled code, and arguably TypeScript output is easier to read.

However, SourceMaps are your best friend, and make sure you are using them when debugging.

Tooling/ES6 Support

Both technologies have nice support for all kinds of frameworks, but in my opinion Babel has much better tools, and it is moving faster. Just look at their setup page to understand the wide support:

https://babeljs.io/docs/setup/

If you are using Node.js or React.js, you should use Babel. However, if you are using .NET, then TypeScript is your friend, and the Visual Studio tools are pretty awesome.

Also be aware that Babel is ahead of TypeScript in terms of EcmaScript support, which should definitely affect your choice:

http://kangax.github.io/compat-table/es6/

Node.js setup of Babel/TypeScript

There are different ways to setup Node to work with Babel and TypeScript. One obvious approach is to pre-compile the scripts and then run them as pure JavaScript, but that is a hassle.

A better approach is to require a module in your entry script and then it will handle dynamic compiling of all the subsequent requires.

require("babel/register");  

The require hook will bind itself to node's require and automatically compile files on the fly.

All subsequent files required by node with the extensions .es6, .es, .jsx and .js will be transformed by Babel. The polyfill is also automatically required.

However, be aware that TypeScript doesn't have the require capability built in, but there are some projects to fill the gap. e.g. https://github.com/theblacksmith/typescript-require

And then you can do:

require('typescript-require');  

After this point, you can require any .ts module just like .js modules. typescript-require will find out and compile the TypeScript file, resolving any necessary dependencies to other scripts.

Final Words

Transpilers are nice, and you must use them, since they do make your code better, even though there is a small overhead in development and debugging, but it is a small price to pay for having more mantainable code.