Babel
02 / 02

Polyfills, TypeScript & the JSX Runtime

Polyfills, TypeScript & the JSX Runtime

Syntax Transforms vs. Polyfills

Syntax transforms rewrite new SYNTAX into equivalent old syntax at compile time (const → var). Polyfills add missing RUNTIME features (Promise, Array.prototype.flat) by including actual implementation code — a syntax transform alone can't conjure a missing built-in.

// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: '> 0.5%, not dead',
      useBuiltIns: 'usage',   // auto-import only the core-js polyfills you actually use
      corejs: 3,
    }],
  ],
};

transform-runtime for Libraries

@babel/plugin-transform-runtime avoids polluting global scope/prototypes by importing helpers and polyfills from a shared runtime package instead — important when authoring a library that shouldn't leak global polyfills into consumers' code. Applications typically just use preset-env's built-in polyfill handling directly.

TypeScript: Strip, Don't Check

# @babel/preset-typescript only strips type annotations, no type-checking
# still run tsc separately in CI to catch real type errors
tsc --noEmit

The Automatic JSX Runtime

// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-react', { runtime: 'automatic' }],
  ],
};

// no more `import React from 'react'` needed just to use JSX —
// Babel imports jsx/jsxs from react/jsx-runtime behind the scenes
// instead of compiling to explicit React.createElement() calls

AST Tooling Beyond Transforms

@babel/parser, @babel/traverse and @babel/generator — the same building blocks Babel uses internally — power codemods (jscodeshift) for large-scale, AST-aware source rewrites, and are used by other tools (Prettier, some ESLint configs) as a JS parsing front-end.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free