Babel (42.4 â) and TypeScript (92.6k â) are two essential tools for JavaScript developers, can be used as standalone tools, or combined with each other to take advantages of both.
Babel is the dominant JavaScript transpiler with hundreds of plugins to transform or polyfill your JavaScript code in whatever ways you want before running in a host environment.
TypeScript allows you to optionally add static type definitions on top of JavaScript, can be considered as a programming language with its own compiler or as a static type checker like Flow.
They have some overlap, but can certainly be used together. You can use Babel as a TypeScript compiler (tsc
). This means much faster compilations, and you can use Babel plugins in TypeScript just as you would with JavaScript.
Before the inception of plugin @babel/preset-typescript, the best build pipeline is still to pass the TypeScript files to the TypeScript compiler and then to Babel afterwards.
There is no need for Babel unless you got to do some case specific transformations.
Babel 7 is useful because it has really robust transforms and polyfills for older browsers. For example example, it will automatically add polyfills for things like promises, or new object methods, as you use them. This has been important for working with enterprise apps.
While Babel can take over transpiling, it doesnât have type-checking built in, and still requires using TypeScript to accomplish that. So even if Babel builds successfully, you might need to check in with TypeScript to catch type errors.
Combining TypeScript with Babel allows you to check for type errors only when youâre ready. This combo also provides faster compilation thanks to Babelâs superior caching and single-file emit architecture.
You have tsc
compile to ES20-whatever, and then have Babel use preset-env to compile that down to whatever the least-qualified browser supports, pulling in polyfills along the way.
You will still need an editor with TypeScript support to benefit from type checking, but doing so will not affect the way their code is built and run.
All sorts of caveat come from the fact that Babel doesnât support cross-file analysis. TypeScript by default compiles an entire project at once, while Babel only compiles one file at a time. This means that Babel doesnât support TypeScript features that require reading multiple files.
Babel doesnât care about your fancy TypeScript types. It just throws them in the trash, without able to check that theyâre right.
TypeScript namespaces and const enums donât work with Babel. Donât worry! These caveats arenât too bad. You donât miss too much here.
Be aware that Babel plugin mimics TypeScript compiler options and doesnât read tsconfig.json
, it means you must provide TypeScript configs twice, some compiler options might be handled differently.
As recommended by TypeScript team, transforming your files to JavaScript works via Babel, TypeScript compiler only for type checking and .d.ts
file generation. This is a common pattern for projects with existing build infrastructure which may have been ported from a JavaScript codebase to TypeScript.
npm install --save-dev \
@babel/core \
@babel/cli \
@babel/preset-env \
@babel/preset-typescript \
typescript
.babelrc.json
{
"presets": [
"@babel/preset-typescript",
[
"@babel/preset-env",
{
"useBuiltIns": "entry",
"targets": "> 0.25%, not dead"
}
]
]
}
tsconfig.json
{
"compilerOptions": {
// Target latest version of ECMAScript.
"target": "esnext",
// Search under node_modules for non-relative imports.
"moduleResolution": "node",
// Process & infer types from .js files.
"allowJs": true,
// Don't emit; allow Babel to transform files.
"noEmit": true,
// Enable strictest settings like strictNullChecks & noImplicitAny.
"strict": true,
// Import non-ES modules as default imports.
"esModuleInterop": true,
// Ensure that .d.ts files are created by tsc, but not .js files
"declaration": true,
"emitDeclarationOnly": true,
// Ensure that Babel can safely transpile files in the TypeScript project
"isolatedModules": true
},
"include": [
"src" // <-- change this to where your source files are
]
}
package.json
{
"scripts": {
"type-check": "tsc --noEmit",
"type-check:watch": "npm run type-check -- --watch",
"build": "npm run build:types && npm run build:js",
"build:types": "tsc --emitDeclarationOnly",
"build:js": "babel src --out-dir lib --extensions \".ts,.tsx\" --source-maps inline"
}
}