Parcel 12 ๐ฆ TypeScript โ SWC-based transpilation
Parcel transpiles TypeScript out of the box, with no configuration required. When it encounters a .ts or .tsx file, it strips the type annotations and converts the remaining code to JavaScript. The default transpiler is not the TypeScript compiler (tsc) and not Babelโit is SWC, a Rust-based compiler that Parcel adopted in the Parcel 2 beta releases. The official Parcel 2 beta 3 announcement states that SWC replaces Babel by default for transpilation, including “compiling JSX and TypeScript,” and that SWC is roughly 20x faster than Babel . The language documentation confirms the behavior: Parcel “automatically transpiles TypeScript whenever you use a .ts or .tsx file,” and “strips the types to convert TypeScript to JavaScript” .
This chapter covers the SWC default, the isolatedModules constraint that follows from Parcel’s per-file processing, the tsconfig.json options that Parcel actually reads, and the alternative transformers that a project can opt into when the default is not sufficient.
Key point: Parcel does not type-check TypeScript. The default SWC transformer strips the types and transpiles the syntax, but it does not verify that the types are correct. The recommended type-checking workflow is the editor for immediate feedback and tsc --noEmit in CI, run separately from the Parcel build .
Why SWC is the default
The speed problem. TypeScript’s official compiler is thorough but not fast. Babel is faster, but it is a JavaScript-based tool with its own parse and transform overhead. SWC is written in Rust and performs the same parse, transform, and code-generation steps with native performance. The Parcel 2 beta announcement describes SWC as the foundation of the new JavaScript transformer and notes that it replaces Babel for TypeScript compilation by default . The result is that a Parcel build with TypeScript files does not pay the Babel cost unless the project explicitly configures a Babel preset.
The zero-configuration problem. Parcel detects the .ts and .tsx extensions and applies the SWC-based transformer automatically. The project does not need a .babelrc, a ts-loader, or a ts-jest configuration. The types are stripped, the modern syntax is downleveled according to the project’s browserslist, and the JSX is converted. The only configuration that Parcel reads from tsconfig.json is a small subset: the JSX options, experimentalDecorators, and useDefineForClassFields .
The Babel fallback problem. SWC is the default, but Babel is still supported. If a .babelrc or babel.config.js containing @babel/preset-typescript is found, Parcel uses Babel to compile the TypeScript files instead of SWC . This is the escape hatch for a project that depends on a Babel plugin that SWC does not implement.
a. The isolatedModules constraint
Parcel processes each file individually. It does not build a cross-file type graph before transpiling, which means some TypeScript features that require type information from another file cannot be compiled. The documentation states this explicitly: Parcel “implicitly enables the isolatedModules option,” and features like const enum that require cross-file type information “will not work” .
The practical consequence is that the code must be written in a way that each file is self-contained from the transpiler’s perspective. A const enum is not supported; a regular enum is. A re-export of a type must use export type so that the transpiler does not attempt to emit a runtime value for it. The documentation recommends enabling isolatedModules in the project’s tsconfig.json so that the IDE and the type-checker warn about these constructs before the Parcel build fails .
b. The tsconfig.json options that Parcel reads
Parcel does not read the full tsconfig.json. It reads the options that affect the transpilation and ignores the rest. The documentation lists the supported options: the JSX options, experimentalDecorators, and useDefineForClassFields . The target and module options are not used, because Parcel’s own browserslist and output format determine those. The baseUrl and paths options are not supported for module resolution; the documentation recommends Parcel’s own tilde or absolute specifiers as the alternative .
A project that depends on paths for import aliases has two options. The parcel-resolver-tspaths plugin adds tsconfig path alias resolution to Parcel v2, and it is installed as a resolver in .parcelrc . The alternative is to use Parcel’s own alias configuration, which is the supported path. The plugin is a community workaround, not a built-in feature.
c. The alternative transformers
Parcel’s default is SWC, but two other transformers are available for projects with specific requirements.
The @parcel/transformer-typescript-tsc plugin uses the official TypeScript compiler instead of SWC. It is the choice when the project uses a tsconfig.json option that SWC does not support, such as a custom target or a compiler option that affects the emit. The plugin is added to the transformers section of .parcelrc for the *.{ts,tsx} pattern . Even with this transformer, Parcel still processes each file individually, so the isolatedModules constraint applies, and the transformer does not perform type checking .
The Babel transformer is used when a .babelrc with @babel/preset-typescript is present. It has the same isolatedModules caveat as the other transformers, and it is the slowest of the three options .
The @parcel/validator-typescript plugin is an experimental type-checking validator. It runs in the background after the bundles are generated, and it requires the include option in tsconfig.json to list all the source files . It is not a replacement for a CI type-check step; it is a convenience for the developer who wants the errors to appear during the Parcel build.
Complete Example Session
// ============================================
// PART 1: THE TYPESCRIPT FILE
// ============================================
// src/app.ts
interface User {
id: string
name: string
}
export function greet(user: User): string {
return `Hello, ${user.name}`
}
// ============================================
// PART 2: THE JAVASCRIPT IMPORT
// ============================================
// src/index.js
import { greet } from './app.ts'
console.log(greet({ id: '1', name: 'Alice' }))
# ============================================
# PART 3: THE BUILD
# ============================================
parcel build src/index.js
# Parcel detects the .ts file.
# SWC strips the types and transpiles the syntax.
# The output is JavaScript.
// ============================================
// PART 4: THE TSCONFIG
// ============================================
{
"compilerOptions": {
"jsx": "react-jsx",
"experimentalDecorators": true,
"isolatedModules": true
}
}
// ============================================
// PART 5: THE CONST ENUM FAILURE
// ============================================
// const enum Colors { Red, Green }
// Parcel's SWC transformer does not support const enum.
// Use a regular enum or a plain object instead.
// ============================================
// PART 6: THE TYPE RE-EXPORT
// ============================================
// Wrong: export { User } from './types'
// Right: export type { User } from './types'
// ============================================
// PART 7: THE TSC TRANSFORMER
// ============================================
// .parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"*.{ts,tsx}": ["@parcel/transformer-typescript-tsc"]
}
}
# ============================================
# PART 8: THE TYPE-CHECK STEP
# ============================================
# package.json
# "scripts": {
# "build": "parcel build src/index.js",
# "typecheck": "tsc --noEmit"
# }
npm run typecheck
// ============================================
// PART 9: THE PATHS PLUGIN
// ============================================
// .parcelrc
{
"extends": "@parcel/config-default",
"resolvers": ["parcel-resolver-tspaths"]
}
// ============================================
// PART 10: THE DECISION
// ============================================
// Default โ SWC, fast, no type-checking
// Unsupported tsconfig โ @parcel/transformer-typescript-tsc
// Babel plugin needed โ .babelrc with @babel/preset-typescript
// Type-checking โ editor + tsc --noEmit in CI
The ten parts covered the TypeScript file, the JavaScript import, the build, the tsconfig, the const enum failure, the type re-export, the TSC transformer, the type-check step, the paths plugin, and the decision.
Quick Reference
Transpiler options
| Transformer | Trigger | Type-checking |
|---|---|---|
| SWC (default) | .ts, .tsx | No |
| Babel | .babelrc with @babel/preset-typescript | No |
| TSC | @parcel/transformer-typescript-tsc in .parcelrc | No |
tsconfig options read by Parcel
| Option | Supported |
|---|---|
| JSX options | Yes |
experimentalDecorators | Yes |
useDefineForClassFields | Yes |
target | No (use browserslist) |
module | No |
baseUrl / paths | No (use plugin or Parcel aliases) |
The isolatedModules constraints
| Construct | Supported |
|---|---|
Regular enum | Yes |
const enum | No |
export type | Yes |
export { Type } | No |
Type-checking workflow
| Context | Tool |
|---|---|
| Editor | TypeScript language service |
| CI | tsc --noEmit |
| Parcel build | No type-checking |
Best Practices
โ Do This:
// Use export type for type re-exports
export type { User } from './types' // โ
// Use a regular enum instead of const enum
enum Colors { Red, Green } // โ
// Enable isolatedModules in tsconfig
{ "compilerOptions": { "isolatedModules": true } } // โ
# Run tsc --noEmit in CI
npm run typecheck // โ
โ Don’t Do This:
// Use const enum with Parcel's default transformer
const enum Colors { Red } // โ
// Re-export a type as a value
export { User } from './types' // โ
# Assume Parcel type-checks the code
parcel build src/index.js // โ (no type-checking)
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
const enum fails | SWC does not support it | Use a regular enum |
| Type re-export fails | The type is emitted as a value | Use export type |
paths aliases do not resolve | Parcel does not read paths | Use parcel-resolver-tspaths or Parcel aliases |
| Type errors reach production | Parcel does not type-check | Run tsc --noEmit in CI |
| Build uses Babel instead of SWC | A .babelrc with @babel/preset-typescript exists | Remove the preset or accept the Babel path |
Real-World Examples
1. Default TypeScript import
import { greet } from './app.ts'
2. The isolatedModules re-export
export type { User } from './types'
3. The TSC transformer
{ "transformers": { "*.{ts,tsx}": ["@parcel/transformer-typescript-tsc"] } }
4. The type-check script
{ "scripts": { "typecheck": "tsc --noEmit" } }
5. The paths plugin
{ "resolvers": ["parcel-resolver-tspaths"] }
6. The tsconfig options
{ "compilerOptions": { "jsx": "react-jsx", "experimentalDecorators": true } }
7. The const enum failure
// const enum Colors { Red } // not supported
8. The regular enum
enum Colors { Red, Green }
9. The Babel fallback
// .babelrc with @babel/preset-typescript
10. The decision
Default โ SWC; unsupported tsconfig โ TSC; Babel plugin โ Babel.
Visual
The transpilation pipeline
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ app.ts โ
โ โ โ
โ โผ โ
โ Parcel detects .ts โ
โ โ โ
โ โผ โ
โ SWC transformer โ
โ โโโ strip types โ
โ โโโ transpile syntax โ
โ โโโ convert JSX โ
โ โ โ
โ โผ โ
โ JavaScript output โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The type-checking boundary
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Parcel build โ
โ โโโ transpiles, no type-checking โ
โ โ
โ Editor โ
โ โโโ type errors as you type โ
โ โ
โ CI โ
โ โโโ tsc --noEmit โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The isolatedModules constraints
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SUPPORTED NOT SUPPORTED โ
โ โ
โ enum const enum โ
โ export type { T } export { T } (type) โ
โ import type { T } import { T } (type) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The transformer selection
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Default โ SWC โ
โ Unsupported tsconfig โ @parcel/transformer-typescript-tsc โ
โ Babel plugin โ .babelrc with @babel/preset-typescript โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Default transpiler | SWC |
| Trigger | .ts, .tsx extension |
| Type-checking | Not performed |
isolatedModules | Implicitly enabled |
const enum | Not supported |
| tsconfig options read | JSX, experimentalDecorators, useDefineForClassFields |
paths resolution | Not supported; use plugin |
| TSC transformer | @parcel/transformer-typescript-tsc |
| Babel fallback | .babelrc with @babel/preset-typescript |
| Type-checking workflow | Editor + tsc --noEmit in CI |
Key takeaways:
- Parcel uses SWC for TypeScript transpilation by default. The Rust-based compiler strips the types and transpiles the syntax faster than Babel or TSC, and it requires no configuration. The
.tsand.tsxextensions are the trigger . - Parcel does not type-check TypeScript. The default transformer, the TSC transformer, and the Babel transformer all strip the types without verifying them. The recommended workflow is the editor for immediate feedback and
tsc --noEmitin CI, run separately from the Parcel build . - The
isolatedModulesconstraint is implicit. Parcel processes each file individually, soconst enumand other cross-file type-dependent features do not work. EnableisolatedModulesintsconfig.jsonso the IDE warns about the unsupported constructs . - Parcel reads a small subset of
tsconfig.json. The JSX options,experimentalDecorators, anduseDefineForClassFieldsare supported.target,module,baseUrl, andpathsare not. Theparcel-resolver-tspathsplugin is the community workaround forpaths. - The TSC transformer is the escape hatch for unsupported options. The
@parcel/transformer-typescript-tscplugin uses the official TypeScript compiler for the transpilation, but it still processes each file individually and does not type-check . - The Babel fallback is for projects that need a Babel plugin. A
.babelrcwith@babel/preset-typescriptswitches the TypeScript compilation to Babel, which is slower than SWC but supports the Babel plugin ecosystem .
Remember: Parcel’s TypeScript support is a transpiler, not a compiler. The SWC default strips the types and converts the syntax, and it does so without configuration and without type-checking. The isolatedModules constraint is the price of the per-file processing: const enum and unqualified type re-exports do not work. The type-checking step is separate: the editor for immediate feedback, and tsc --noEmit in CI. The TSC and Babel transformers exist for the projects that need them, but they share the same per-file limitation and the same absence of type-checking.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!