Babel 7 separates TypeScript transformation from type checking
Babel 7 can process TypeScript source inside an existing Babel pipeline. Type checking remains a separate compiler operation, and single-file transformation places limits on the supported constructs.
Adopting type annotations can require changing a working build before a project has learned whether the annotations help. Babel users already have a transformation pipeline, often with configuration tied to their target browsers. Babel 7 adds a route for those projects to accept TypeScript source while retaining Babel's role in producing JavaScript.
The joint TypeScript announcement on August 27 explains that setup difficulty was a recurring concern among Babel users. The teams collaborated on TypeScript support, and the Babel 7 release announcement describes the resulting preset. Babel parses and transforms the source, while TypeScript remains responsible for checking its types.
I am impressed by the web ecosystem around TypeScript even while remaining circumspect about the language. Making its checking available without replacing an established JavaScript pipeline is useful. The arrangement is clearest when the build states which tool produces code and which tool decides whether the type relationships are valid.
Removing a type does not check it
Babel's TypeScript support can erase interfaces and annotations while leaving executable JavaScript. A declaration's type may be inconsistent with its initializer, yet that inconsistency does not prevent Babel from performing the transformation.
const retries: number = "three";
The annotation claims a number, and the initializer supplies a string. A type checker can diagnose that relationship. A transform that removes the annotation can still produce JavaScript assigning the string. Successful transformation establishes that the tool could process the syntax, not that the declared types agree with the program.
This distinction is explicit in the TypeScript team's announcement. Babel compiles regardless of type errors, and does not read declaration files to establish compatibility. A separate TypeScript operation provides those checks. Editor feedback can make the arrangement convenient during development, while a build or continuous-integration operation can make checking an explicit condition for acceptance.
The separation also changes how failures are interpreted. A syntax or transformation error belongs to the code-production path. A type error can occur while JavaScript generation succeeds. Treating one process's success as the result of both would discard information the workflow deliberately assigns to the other process.
No runtime validation appears merely because an annotation existed in the source. The generated program receives the runtime values its JavaScript operations produce. The type checker helps detect disagreements before execution, but a stripped declaration does not become a test executed when the value arrives.
The preset joins the existing transformation configuration
The announcement introduces @babel/preset-typescript. Its example combines the TypeScript preset with the environment preset and proposal plugins for class properties and object rest/spread. Those are separate transformation responsibilities, so adding TypeScript parsing is not equivalent to configuring every desired JavaScript feature.
{
"presets": [
"@babel/env",
"@babel/preset-typescript"
],
"plugins": [
"@babel/proposal-class-properties",
"@babel/proposal-object-rest-spread"
]
}
This is the release announcement's configuration shape for the Babel 7 package names available at launch. The project's actual dependency list still needs those packages installed. Configuration expresses which transforms participate; it does not obtain their implementations by itself.
The same announcement shows the CLI selecting .ts and .tsx input extensions and writing to a library output directory. This is a practical detail because a transform can support a file's syntax only after the build actually includes that file as an input. Merely adding a preset does not establish that an existing command's file-extension selection has changed.
The preset implementation tagged at Babel 7.0.0 makes the extension distinction visible. Its default overrides match .ts and .tsx separately, enabling the TSX parser mode for the latter. It also checks the relationship between the explicit isTSX and allExtensions options.
These details explain why a preset belongs within a larger build configuration. Source selection and parser mode must agree with the files, while other plugins own the JavaScript features that require transformation. The TypeScript preset supplies a particular stage in that process.
TypeScript can check without emitting another copy
The recommended TypeScript configuration uses noEmit so Babel owns JavaScript output. It also enables strict checking and isolatedModules, with node-style module resolution and interoperability settings. The compiler can then inspect the same source without creating a competing set of generated JavaScript files.
{
"compilerOptions": {
"target": "esnext",
"moduleResolution": "node",
"noEmit": true,
"strict": true,
"isolatedModules": true,
"esModuleInterop": true
},
"include": ["src"]
}
Here target describes the compiler's checking configuration, while noEmit prevents that compiler invocation from producing JavaScript. Babel's configuration remains responsible for its own output transformations. Selecting a TypeScript target does not silently configure Babel's browser targets.
The release announcement also offers allowJs for projects that include JavaScript files and describes running either tool in watch mode. Those choices support gradual adoption without requiring every file to acquire TypeScript syntax immediately. They do not merge the tools' responsibilities into one implicit operation.
I prefer the explicit ownership this arrangement makes possible. The project can identify the command that generates its runnable files and the command that checks their types. The useful result is a workflow with both obligations accounted for, not a claim that one successful command has performed work it was never designed to do.
Single-file emission has compatibility limits
Babel's architecture transforms one file at a time. The TypeScript announcement lists unsupported constructs at launch, including namespaces, merged enum declarations and legacy import = or export = syntax. It recommends isolatedModules so TypeScript can identify some constructs that need information beyond the single file for emission.
The tagged TypeScript transform gives concrete examples. Its visitor rejects runtime namespaces and throws errors for import-equals declarations and export assignments. Other visitors remove interface declarations, type aliases and type annotations.
That difference matters when describing support. Some TypeScript constructs are declaration information that can disappear. Others require executable output with semantics the transform must implement. Supporting annotations therefore does not imply that every TypeScript language construct can be handled through erasure alone.
The transform also implements parameter properties by adding assignments in a constructor. Its code places those assignments after an initial super() call when present. This is executable transformation, showing why a precise account of Babel's TypeScript support must include more than the phrase stripping types.
Reading the release's limitations prevents a migration from assuming interchangeability between the tools. A project using supported syntax can retain its Babel pipeline and add checking, while one relying on unsupported emit constructs has a concrete compatibility problem to resolve. The release announcement still recommends the integrated TypeScript compiler pipeline for many existing TypeScript projects.
Import removal provides another example of the information available to the transform. The tagged implementation inspects the local binding's reference paths to decide whether an imported name appears only in type positions. A type-only use can disappear with the declaration, while a value use needs its runtime import retained. This decision uses the current file's syntax and bindings, consistent with the architecture described in the announcement.
The implementation gives the JSX factory name special treatment. If the imported binding matches that name, it also looks for JSX elements or fragments before deciding that the import is type-only. An import can be required by the eventual JavaScript factory call even when the source does not contain an ordinary explicit call to the imported name. The check preserves that relationship between JSX syntax and generated code.
Babel 7 also moves its official packages into the @babel scope, as its own release post explains. The package names in the setup example belong to that change. The environment preset replaces the yearly presets, and proposal features use separately selected proposal plugins. Consequently, adding TypeScript support to an existing Babel configuration can involve ordinary Babel 7 configuration changes as well as the new preset. Those are distinct migration concerns, even when a project performs them together.
The release also distinguishes runtime helper packages from packages supplying polyfilled APIs, making their different contents explicit.
Syntax transformation and runtime APIs remain separate
The Babel announcement also distinguishes transformation from polyfills. Converting syntax for an older runtime does not itself provide missing built-in objects such as Promise or Symbol. Babel describes separate mechanisms and configuration for supplying those APIs.
That distinction persists when the source happens to be TypeScript. An annotation can describe an API, and a checker can accept a program against declarations for that API, without causing the browser to implement it. The delivered program still needs its runtime dependencies. Babel 7's new support makes TypeScript source available to the existing transformation process while keeping type checking and runtime capability as separate, explicit parts of the build.