The TypeScript Compiler (tsc) is the tool that:
π Converts TypeScript code (.ts / .tsx files) into plain JavaScript (.js)
π Checks your code for type errors before compiling
β The output JavaScript can run anywhere JavaScript runs β browsers, Node.js, etc.
β The compiler makes sure your code is type-safe (according to the types you wrote or inferred).
π Main responsibilities of tsc
Transpile TypeScript (and modern JS features) into compatible JavaScript
Check types and report type errors
Handle advanced features like decorators, namespaces, and modules
Support config-driven builds via
tsconfig.json
π Basic tsc commands
1οΈβ£ Compile a single file:
tsc index.tsThis creates index.js in the same folder.
2οΈβ£ Compile all files in your project (when tsconfig.json is present):
tscor
npm run build(if you defined a build script)
3οΈβ£ Watch files (automatic recompile on save):
tsc --watchπ This is useful during development for faster feedback.
βοΈ tsconfig.json and Compiler Options
You can control how tsc works using a tsconfig.json file.
tsc --initcreates a default config.
Common options you might see:
{
"compilerOptions": {
"target": "es6", // JS version output
"module": "commonjs", // Module system (commonjs, es6, etc.)
"outDir": "./dist", // Output directory for JS files
"strict": true, // Enable all strict type checks
"esModuleInterop": true, // Allow default imports from commonjs
"sourceMap": true // Generate source maps for debugging
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}π This way, tsc knows how to process your files and where to put the output.
π Type checking
Even if you donβt want to generate JavaScript, you can run:
tsc --noEmitβ
This checks types but doesnβt produce .js files. Useful for CI and code quality checks!
π Bonus Tips
You can use
tscwith build tools (Webpack, Vite) to integrate into modern workflows.Tools like Babel can be used alongside
tscto handle transpiling + polyfilling.TypeScript compiler API allows you to build custom tooling (advanced).
π Example workflow
tsc --init // Create config
tsc // Compile all TypeScript files
tsc --watch // Recompile automatically on file change
tsc --noEmit // Only check types<div class="infographic-ts" id="infographic-ts">
<style>
.infographic-ts {
--body-font: system-ui, -apple-system, sans-serif;
--mono-font: ui-monospace, SFMono-Regular, Consolas, "Courier New", monospace;
--ed-bg: #1e1e1e;
--ed-bar: #2a2a2a;
--ed-text: #d4d4d4;
--ed-muted: #8a8a8a;
--ed-prompt: #4ec9b0;
--ed-out: #d4d4d4;
--ed-err: #f14c4c;
--ed-ok: #4ec9b0;
--ed-cursor: #d4d4d4;
--run-bg: #2e7d46;
--run-bg-hover: #35924f;
max-width: 720px;
margin: 0 auto;
box-sizing: border-box;
background: transparent;
font-family: var(--body-font);
}
.infographic-ts * { box-sizing: border-box; }
.code-window { background: var(--ed-bg); border-radius: 8px; overflow: hidden; margin-bottom: 1.25rem; }
.code-window:last-child { margin-bottom: 0; }
.code-topbar { display: flex; align-items: center; justify-content: space-between;
padding: 0.55rem 0.8rem; background: var(--ed-bar); }
.code-dots { display: flex; gap: 6px; }
.code-dot { width: 10px; height: 10px; border-radius: 50%; }
.code-dot.r { background: #ff5f57; }
.code-dot.y { background: #febc2e; }
.code-dot.g { background: #28c840; }
.code-filename { font-family: var(--mono-font); font-size: 0.76rem; color: var(--ed-muted); }
.run-btn { display: inline-flex; align-items: center; gap: 0.35rem; background: var(--run-bg);
color: #fff; border: none; border-radius: 4px; padding: 0.35rem 0.75rem; font-size: 0.76rem;
font-family: var(--body-font); font-weight: 500; cursor: pointer; }
.run-btn:hover { background: var(--run-bg-hover); }
.run-btn:disabled { opacity: 0.55; cursor: default; }
.run-btn svg { width: 11px; height: 11px; }
.code-body { padding: 0.9rem 1.25rem; font-family: var(--mono-font); font-size: 0.83rem;
line-height: 1.6; color: var(--ed-out); white-space: pre; overflow-x: auto; }
.prompt { color: var(--ed-prompt); }
.console { padding: 0 1.25rem; max-height: 0; overflow: hidden;
font-family: var(--mono-font); font-size: 0.8rem; line-height: 1.65;
transition: max-height 0.35s ease, padding 0.35s ease; }
.console.show { max-height: 220px; padding: 0 1.25rem 1rem; overflow-y: auto; }
.console-line { color: var(--ed-out); white-space: pre-wrap; }
.console-line.err { color: var(--ed-err); }
.console-line.ok { color: var(--ed-ok); }
.cursor { display: inline-block; width: 7px; height: 14px; background: var(--ed-cursor);
vertical-align: text-bottom; animation: blink 1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .cursor { animation: none; } }
</style>
<div class="code-window">
<div class="code-topbar">
<div class="code-dots"><span class="code-dot r"></span><span class="code-dot y"></span><span class="code-dot g"></span></div>
<span class="code-filename">terminal</span>
<button class="run-btn" id="btn1" type="button">
<svg viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg>
run
</button>
</div>
<div class="code-body"><span class="prompt">$</span> tsc --init</div>
<div class="console" id="c1"></div>
</div>
<div class="code-window">
<div class="code-topbar">
<div class="code-dots"><span class="code-dot r"></span><span class="code-dot y"></span><span class="code-dot g"></span></div>
<span class="code-filename">terminal</span>
<button class="run-btn" id="btn2" type="button">
<svg viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg>
run
</button>
</div>
<div class="code-body"><span class="prompt">$</span> tsc</div>
<div class="console" id="c2"></div>
</div>
<div class="code-window">
<div class="code-topbar">
<div class="code-dots"><span class="code-dot r"></span><span class="code-dot y"></span><span class="code-dot g"></span></div>
<span class="code-filename">terminal</span>
<button class="run-btn" id="btn3" type="button">
<svg viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg>
run
</button>
</div>
<div class="code-body"><span class="prompt">$</span> tsc --watch</div>
<div class="console" id="c3"></div>
</div>
<div class="code-window">
<div class="code-topbar">
<div class="code-dots"><span class="code-dot r"></span><span class="code-dot y"></span><span class="code-dot g"></span></div>
<span class="code-filename">terminal</span>
<button class="run-btn" id="btn4" type="button">
<svg viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg>
run
</button>
</div>
<div class="code-body"><span class="prompt">$</span> tsc --noEmit</div>
<div class="console" id="c4"></div>
</div>
<script>
(function () {
var wrapper = document.currentScript.closest('.infographic-ts')
|| document.querySelector('.infographic-ts');
var root = wrapper;
function line(consoleEl, cls, text) {
var el = document.createElement('div');
el.className = 'console-line ' + (cls || '');
el.textContent = text;
consoleEl.appendChild(el);
consoleEl.scrollTop = consoleEl.scrollHeight;
return el;
}
function blank(consoleEl) { line(consoleEl, '', '\u00a0'); }
function time() {
var d = new Date();
var h = d.getHours() % 12 || 12;
var m = ('0' + d.getMinutes()).slice(-2);
var s = ('0' + d.getSeconds()).slice(-2);
return h + ':' + m + ':' + s + (d.getHours() >= 12 ? ' PM' : ' AM');
}
var btn1 = root.querySelector('#btn1');
var c1 = root.querySelector('#c1');
btn1.addEventListener('click', function () {
btn1.disabled = true;
c1.innerHTML = '';
c1.classList.add('show');
blank(c1);
line(c1, 'ok', 'Created a new tsconfig.json with:');
blank(c1);
line(c1, '', ' target: es2016');
line(c1, '', ' module: commonjs');
line(c1, '', ' strict: true');
line(c1, '', ' esModuleInterop: true');
blank(c1);
line(c1, '', 'You can learn more at https://aka.ms/tsconfig');
btn1.disabled = false;
});
var btn2 = root.querySelector('#btn2');
var c2 = root.querySelector('#c2');
btn2.addEventListener('click', function () {
btn2.disabled = true;
c2.innerHTML = '';
c2.classList.add('show');
blank(c2);
line(c2, '', 'src/greet.ts \u2192 dist/greet.js');
line(c2, '', 'src/utils.ts \u2192 dist/utils.js');
line(c2, '', 'src/index.ts \u2192 dist/index.js');
blank(c2);
line(c2, 'ok', 'Done \u2014 no console output means no type errors.');
btn2.disabled = false;
});
var btn3 = root.querySelector('#btn3');
var c3 = root.querySelector('#c3');
btn3.addEventListener('click', function () {
btn3.disabled = true;
c3.innerHTML = '';
c3.classList.add('show');
blank(c3);
line(c3, '', '[' + time() + '] Starting compilation in watch mode\u2026');
blank(c3);
var okLine = line(c3, 'ok', '[' + time() + '] Found 0 errors. Watching for file changes.');
var cursor = document.createElement('span');
cursor.className = 'cursor';
okLine.appendChild(cursor);
setTimeout(function () {
cursor.remove();
blank(c3);
line(c3, '', '[' + time() + '] File change detected. Starting incremental compilation\u2026');
blank(c3);
var okLine2 = line(c3, 'ok', '[' + time() + '] Found 0 errors. Watching for file changes.');
var cursor2 = document.createElement('span');
cursor2.className = 'cursor';
okLine2.appendChild(cursor2);
}, 2600);
});
var btn4 = root.querySelector('#btn4');
var c4 = root.querySelector('#c4');
btn4.addEventListener('click', function () {
btn4.disabled = true;
c4.innerHTML = '';
c4.classList.add('show');
blank(c4);
line(c4, 'ok', 'Found 0 errors.');
line(c4, '', 'No .js files were written \u2014 types checked only.');
btn4.disabled = false;
});
})();
</script>
</div>π‘ Summary
Feature | Purpose |
|---|---|
| Transpile TypeScript to JavaScript |
| Live compile on file changes |
| Control compiler settings |
| Type check only, no JS output |