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 --noEmitThe 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() callsAST 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