Converting TypeScript to JavaScript is a common task when publishing npm packages, supporting legacy environments, or removing type overhead from production bundles. Whether you need to convert TS to JS online quickly or set up an automated build pipeline, understanding what gets stripped and what stays is essential. This comprehensive guide covers the TypeScript compiler (tsc), Babel, esbuild, online conversion tools, enum handling, project migration strategies, and best practices for TypeScript to JavaScript conversion.
Try our free online TypeScript to JavaScript Converter.
Why Convert TypeScript to JavaScript?
TypeScript is a superset of JavaScript that adds static type checking, interfaces, enums, generics, and other features. However, browsers and Node.js runtimes execute JavaScript, not TypeScript. Every TypeScript file must be compiled (or transpiled) to JavaScript before it can run. This conversion removes all type annotations while preserving the runtime logic.
Common scenarios for TS to JS conversion include: publishing an npm library that must work in plain JavaScript projects, deploying to environments that do not support TypeScript natively, debugging compiled output to understand what TypeScript generates, migrating away from TypeScript in legacy projects, and reducing build complexity in small scripts or prototypes.
Understanding what changes during conversion helps you write better TypeScript. Type annotations, interfaces, type aliases, and declare blocks are erased completely. Enums, decorators, class fields, and namespace declarations generate runtime JavaScript code. Knowing this distinction is key to predicting your output.
What Gets Stripped: Types vs Runtime Code
When converting TypeScript to JavaScript, it is critical to understand which TypeScript features are erased (type-only) and which produce runtime code:
| TypeScript Feature | Erased? | JavaScript Output |
|---|---|---|
Type annotations (: string, : number) | Yes | Removed entirely |
Interfaces (interface User {}) | Yes | Removed entirely |
Type aliases (type ID = string) | Yes | Removed entirely |
Generics (<T>) | Yes | Removed entirely |
as type assertions | Yes | Expression kept, assertion removed |
Enums (enum Direction {}) | No | Generates IIFE or object |
const enum | Depends | Inlined at usage sites by default |
Decorators (@Injectable()) | No | Generates decorator call code |
Namespace (namespace Foo {}) | No | Generates IIFE |
Class fields with declare | Yes | Removed entirely |
Parameter properties (constructor(public name: string)) | No | Generates assignment in constructor |
Methods to Convert TypeScript to JavaScript
Method 1: TypeScript Compiler (tsc)
The official TypeScript compiler (tsc) is the most reliable way to convert TypeScript to JavaScript. It performs full type checking before emitting JavaScript output. Install with npm install -D typescript:
# Install TypeScript
npm install -D typescript
# Create tsconfig.json
npx tsc --init
# tsconfig.json key settings for conversion
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"outDir": "./dist",
"rootDir": "./src",
"declaration": true, // Generate .d.ts files
"sourceMap": true, // Generate source maps
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}
# Compile single file
npx tsc src/app.ts --outDir dist
# Compile entire project
npx tsc
# Type-check only (no output)
npx tsc --noEmitMethod 2: Babel with @babel/preset-typescript
Babel strips TypeScript types without performing type checking, making it faster than tsc for build pipelines where type checking runs separately. Install with npm install -D @babel/core @babel/cli @babel/preset-typescript:
# Install Babel with TypeScript preset
npm install -D @babel/core @babel/cli @babel/preset-typescript
# babel.config.json
{
"presets": ["@babel/preset-typescript"]
}
# Compile a single file
npx babel src/app.ts --out-file dist/app.js --extensions ".ts,.tsx"
# Compile entire directory
npx babel src --out-dir dist --extensions ".ts,.tsx"
# Note: Babel does NOT type-check!
# Run tsc separately for type safety:
npx tsc --noEmit && npx babel src --out-dir dist --extensions ".ts,.tsx"Method 3: esbuild (Fastest)
esbuild is an extremely fast JavaScript bundler written in Go that natively supports TypeScript. It strips types without type checking, similar to Babel but orders of magnitude faster:
# Install esbuild
npm install -D esbuild
# Bundle a TypeScript entry point to JavaScript
npx esbuild src/app.ts --bundle --outfile=dist/app.js --platform=node
# Transpile without bundling (preserves module structure)
npx esbuild src/**/*.ts --outdir=dist --format=esm
# Watch mode for development
npx esbuild src/app.ts --bundle --outfile=dist/app.js --watch
# Build with minification for production
npx esbuild src/app.ts --bundle --minify --outfile=dist/app.min.jsMethod 4: Online Converter
For quick one-off conversions, an online TypeScript to JavaScript converter lets you paste TypeScript code and instantly see the JavaScript output. Our free tool at DevToolBox handles all TypeScript syntax including enums, decorators, and generic type parameters. No installation needed.
Handling TypeScript Enums in JavaScript
TypeScript enums are one of the few TypeScript features that generate runtime JavaScript code. Understanding their compiled output helps you work with the converted JavaScript:
// === TypeScript: Numeric enum ===
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
// === Compiled JavaScript ===
var Direction;
(function (Direction) {
Direction[Direction["Up"] = 0] = "Up";
Direction[Direction["Down"] = 1] = "Down";
Direction[Direction["Left"] = 2] = "Left";
Direction[Direction["Right"] = 3] = "Right";
})(Direction || (Direction = {}));
// Direction[0] === "Up" (reverse lookup)
// Direction.Up === 0 (forward lookup)
// === TypeScript: String enum ===
enum Color {
Red = "#FF0000",
Green = "#00FF00",
Blue = "#0000FF"
}
// === Compiled JavaScript ===
var Color;
(function (Color) {
Color["Red"] = "#FF0000";
Color["Green"] = "#00FF00";
Color["Blue"] = "#0000FF";
})(Color || (Color = {}));
// No reverse mapping for string enums
// === TypeScript: const enum (inlined) ===
const enum Status {
Active = "ACTIVE",
Inactive = "INACTIVE"
}
const s = Status.Active;
// === Compiled JavaScript (const enum is inlined) ===
const s = "ACTIVE"; // enum declaration removed entirelyNumeric enums compile to an IIFE (Immediately Invoked Function Expression) that creates a bidirectional mapping object. This means you can look up both the name by value and the value by name.
String enums compile to a simpler object with only forward mappings (name to value). There is no reverse mapping because string values are not guaranteed to be unique.
const enums are inlined at usage sites by default, meaning the enum declaration is completely removed and each reference is replaced with its literal value. This produces the most efficient JavaScript but means you lose the runtime object. Use --preserveConstEnums to keep the runtime object if needed.
Preserving Runtime Behavior
When converting TypeScript to JavaScript, certain patterns require special attention to preserve correct runtime behavior:
Optional chaining and nullish coalescing: TypeScript's ?. and ?? operators are standard JavaScript (ES2020). If your target is ES2019 or earlier, tsc will emit polyfilled versions. If targeting ES2020+, they pass through unchanged.
Parameter properties: TypeScript's constructor(public name: string) shorthand generates assignment statements in the constructor body. The resulting JavaScript is equivalent to manually writing this.name = name.
// === TypeScript: Parameter properties ===
class User {
constructor(
public name: string,
private age: number,
readonly id: string
) {}
}
// === Compiled JavaScript ===
class User {
constructor(name, age, id) {
this.name = name;
this.age = age;
this.id = id;
}
}
// === TypeScript: import type (always erased) ===
import type { UserType } from './types'; // Erased completely
import { createUser } from './utils'; // Kept (runtime value)Import elision: TypeScript automatically removes imports that are only used as types. If an import is used both as a type and a value, TypeScript keeps it. Use import type { Foo } to explicitly mark type-only imports and avoid accidental side effects.
Project Migration: TypeScript to JavaScript
Migrating an entire project from TypeScript to JavaScript is a larger undertaking. Here is a practical approach:
- Compile with
tsc --declaration: Generate both.jsand.d.tsfiles. The.d.tsfiles preserve type information for any TypeScript consumers. - Verify output: Run your test suite against the compiled JavaScript to ensure behavior is identical.
- Replace source files: Swap
.tsfiles with the compiled.jsfiles. Keep.d.tsfiles if the project is consumed as a library. - Update build tooling: Remove TypeScript from devDependencies, update build scripts, and remove
tsconfig.jsonif fully migrating away. - Add JSDoc annotations: For projects that still want type checking without TypeScript, use JSDoc comments with
// @ts-checkandjsconfig.jsonto get IDE support.
Best Practices for TypeScript to JavaScript Conversion
Use tsc for correctness, esbuild for speed: Run tsc --noEmit for type checking in CI, and use esbuild or Babel for fast builds in development. This gives you both safety and speed.
Set the correct target: The target in tsconfig.json determines which JavaScript version is emitted. Use ES2020 or later for modern environments, ES5 for legacy browser support.
Use module: "ESNext" for tree shaking: ES modules enable bundlers to eliminate unused exports. Avoid "CommonJS" unless targeting Node.js without ESM support.
Prefer import type for type-only imports: This ensures type imports are always erased and prevents accidentally importing runtime code from type-only modules.
Be cautious with enums: If you plan to convert to JavaScript, prefer union types (type Direction = "up" | "down") over enums, as unions are erased completely while enums generate runtime code.
Test the compiled output: Always run your tests against the compiled JavaScript, not just the TypeScript source. This catches issues with enum compilation, decorator output, and module resolution.
Use source maps: Enable "sourceMap": true in tsconfig.json so you can debug the original TypeScript when issues arise in the compiled JavaScript.
Related tools: JSON to TypeScript for generating interfaces, JSON Formatter for validating JSON, and Diff Checker for comparing TypeScript and JavaScript output.
TypeScript to JavaScriptJSON to TypeScriptJSON FormatterDiff Checker
Frequently Asked Questions
Can I convert TypeScript to JavaScript online without installing anything?
Yes. Our free TypeScript to JavaScript converter at DevToolBox lets you paste any TypeScript code and instantly see the compiled JavaScript output. It handles all TypeScript features including generics, enums, interfaces, type aliases, and decorators. No Node.js or npm installation required.
What is the difference between tsc, Babel, and esbuild for TypeScript compilation?
tsc is the official TypeScript compiler that performs full type checking and emits JavaScript. It is the most correct but slowest option. Babel with @babel/preset-typescript strips types without checking them, offering faster builds. esbuild is written in Go and is the fastest option (10-100x faster than tsc), also stripping types without checking. For production, use tsc --noEmit for type checking plus esbuild for fast JavaScript emission.
What happens to TypeScript interfaces and type aliases when converted to JavaScript?
Interfaces and type aliases are completely erased during compilation. They exist only at compile time for type checking and generate zero JavaScript output. This is true for all conversion methods (tsc, Babel, esbuild). Only runtime constructs like enums, decorators, and namespace declarations produce JavaScript code.
How do TypeScript enums compile to JavaScript?
Numeric enums compile to an IIFE that creates a bidirectional mapping object (you can look up name by value and value by name). String enums compile to a forward-only mapping object. const enum values are inlined at usage sites, removing the enum object entirely. Use --preserveConstEnums to keep the runtime object.
Should I convert an existing TypeScript project to JavaScript?
In most cases, no. TypeScript provides significant benefits for code quality, refactoring safety, and developer experience. Consider converting only if: the project is very small and TypeScript adds unnecessary complexity, the team has no TypeScript expertise, or you are publishing a library and want to provide pre-compiled JavaScript with .d.ts type definitions.
Converting TypeScript to JavaScript is straightforward once you understand what gets stripped (types, interfaces, aliases) and what generates runtime code (enums, decorators, namespaces). Use tsc for correctness, esbuild for speed, and our free online converter for quick one-off tasks. This guide covers everything you need for confident TS to JS conversion.
Convert TypeScript to JavaScript instantly with our free online tool.
Related Developer Tools and Guides
- TypeScript to JavaScript Converter - Convert TS to JS online instantly
- JSON to TypeScript Converter - Generate TypeScript interfaces from JSON
- JSON Formatter - Format and validate JSON data
- Diff Checker - Compare TypeScript and JavaScript output
- JSON to Go Converter - Create Go structs from JSON
- JSON to Kotlin Converter - Generate Kotlin data classes
- Regex Tester - Test regular expressions online
- Base64 Encoder/Decoder - Encode and decode Base64
- JSON to TypeScript Guide - Complete guide to generating TS interfaces
- TypeScript vs JavaScript - When to use TypeScript