π TypeScript is a programming language developed and maintained by Microsoft that builds on JavaScript by adding static types.
In simple terms:
TypeScript is JavaScript with types.
It compiles to plain JavaScript, so it can run anywhere JavaScript runs (browsers, Node.js, etc.).
It helps catch errors at compile time rather than at runtime by letting you define what kinds of values your variables, functions, and objects can have.
β¨ Key Features of TypeScript
β Optional static typing β You can define types for variables, function parameters, return values, and objects.
β Modern JavaScript support β TypeScript supports the latest JavaScript (ES6+) features and compiles them down for older environments.
β Enhanced tooling β Better autocomplete, navigation, and refactoring support in editors like VS Code.
β Scalability β Makes it easier to work on large codebases and with teams.
β Type inference β TypeScript can often figure out the type for you without you explicitly writing it.
<div class="infographic-ts" id="infographic-ts">
<style>
.infographic-ts {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--error: #c0392b;
--error-soft: #fbe9e7;
--ok: #147a56;
--ok-soft: #e1f5ee;
--str: #b8461f;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', system-ui, sans-serif;
max-width: 880px;
margin: 0 auto;
box-sizing: border-box;
background: transparent;
color: var(--ink);
font-family: var(--body-font);
}
.infographic-ts[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #b3b0a6;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #3a3f4c;
--error: #f28b82;
--error-soft: #3a2222;
--ok: #6fd6ac;
--ok-soft: #143028;
--str: #f0a17c;
}
.infographic-ts * { box-sizing: border-box; }
.ts-eyebrow { font-size: 0.78rem; letter-spacing: 0.08em; text-transform: uppercase;
color: var(--accent); text-align: center; margin: 0 0 0.6rem; font-weight: 500; }
.ts-title { font-family: var(--display-font); font-weight: 500; text-align: center;
font-size: clamp(1.6rem, 4.5vw, 2.3rem); margin: 0 0 0.6rem; line-height: 1.2; }
.ts-subtitle { text-align: center; color: var(--ink-soft); max-width: 480px; margin: 0 auto 2.25rem;
font-size: 1rem; line-height: 1.55; }
.ts-hero { display: flex; align-items: center; justify-content: center; gap: 1.4rem;
padding: 0.5rem 0 2.5rem; flex-wrap: wrap; }
.ts-filecard { position: relative; width: 96px; height: 118px; background: var(--paper-alt);
border: 1.5px solid var(--line); display: flex; flex-direction: column; align-items: center;
justify-content: flex-end; padding-bottom: 0.7rem; }
.ts-filecard svg.ts-fileicon { width: 38px; height: 38px; color: var(--ink-soft); margin-bottom: 0.6rem; }
.ts-filecard .ts-fileext { font-size: 0.95rem; font-weight: 500; }
.ts-filecard.ts-src .ts-fileext { color: var(--accent); }
.ts-filecard.ts-src svg.ts-fileicon { color: var(--accent); }
.ts-filecard.ts-out .ts-fileext { color: var(--ink-soft); }
.ts-badge { position: absolute; bottom: -10px; right: -10px; width: 32px; height: 32px;
background: var(--accent); border-radius: 50%; display: flex; align-items: center;
justify-content: center; border: 2px solid var(--paper); }
.ts-badge svg { width: 17px; height: 17px; color: var(--paper); }
.ts-hero-mid { display: flex; flex-direction: column; align-items: center; gap: 0.4rem;
color: var(--ink-soft); max-width: 130px; }
.ts-hero-mid svg { width: 26px; height: 26px; }
.ts-hero-mid span { font-size: 0.78rem; text-align: center; line-height: 1.4; }
.ts-scene-block { margin-bottom: 2rem; }
.ts-scene-top { display: flex; align-items: baseline; justify-content: space-between;
margin-bottom: 0.75rem; }
.ts-scene-name { font-weight: 500; font-size: 1.05rem; }
.ts-scene-tag { font-size: 0.82rem; color: var(--ink-soft); }
.ts-scene { position: relative; height: 100px; background: var(--paper-alt);
border: 1.5px solid var(--line); overflow: visible; }
.ts-track-line { position: absolute; left: 0; right: 0; top: 50%; height: 0;
border-top: 2px dashed var(--line); }
.ts-token { position: absolute; top: 50%; transform: translateY(-50%); width: 46px; height: 46px;
display: flex; align-items: center; justify-content: center; font-size: 0.82rem; font-weight: 500;
color: #fff; transition: left 1.1s cubic-bezier(.4,0,.2,1); z-index: 2; }
.ts-token.num { border-radius: 50%; background: var(--accent); }
.ts-token.str { border-radius: 8px; background: var(--str); }
.ts-token.blocked { animation: ts-shake 0.4s; }
@keyframes ts-shake {
0%, 100% { transform: translateY(-50%) translateX(0); }
20% { transform: translateY(-50%) translateX(-6px); }
40% { transform: translateY(-50%) translateX(6px); }
60% { transform: translateY(-50%) translateX(-4px); }
80% { transform: translateY(-50%) translateX(4px); }
}
.ts-gate { position: absolute; top: 50%; transform: translate(-50%, -50%); width: 58px; height: 58px;
border-radius: 50%; background: var(--paper); border: 2px solid var(--line); display: flex;
align-items: center; justify-content: center; z-index: 1; transition: border-color 0.25s, background 0.25s; }
.ts-gate svg { width: 26px; height: 26px; color: var(--ink-soft); transition: color 0.25s; }
.ts-gate.ok { border-color: var(--ok); background: var(--ok-soft); }
.ts-gate.ok svg { color: var(--ok); }
.ts-gate.blocked { border-color: var(--error); background: var(--error-soft); }
.ts-gate.blocked svg { color: var(--error); }
.ts-endmark { position: absolute; top: 50%; transform: translateY(-50%); width: 34px; height: 34px;
opacity: 0; transition: opacity 0.35s; }
.ts-endmark.show { opacity: 1; }
.ts-endmark svg { width: 100%; height: 100%; }
.ts-endmark.bug svg { color: var(--error); }
.ts-endmark.clean svg { color: var(--ok); }
.ts-controls { display: flex; align-items: center; gap: 1rem; margin-top: 0.9rem; flex-wrap: wrap; }
.ts-btn { font: inherit; font-size: 0.88rem; font-weight: 500; background: var(--accent);
border: none; color: #fff; padding: 0.55rem 1.1rem; cursor: pointer; border-radius: 4px;
display: inline-flex; align-items: center; gap: 0.45rem; }
.ts-btn:hover { opacity: 0.88; }
.ts-btn svg { width: 14px; height: 14px; }
.ts-note { font-size: 0.88rem; color: var(--ink); min-height: 1.3em; flex: 1 1 220px; }
.ts-note.err { color: var(--error); }
.ts-note.ok { color: var(--ok); }
.ts-legend { display: flex; gap: 1.4rem; justify-content: center; margin-bottom: 1.75rem;
font-size: 0.8rem; color: var(--ink-soft); flex-wrap: wrap; }
.ts-legend-item { display: flex; align-items: center; gap: 0.4rem; }
.ts-legend-swatch { width: 16px; height: 16px; flex-shrink: 0; }
.ts-legend-swatch.num { border-radius: 50%; background: var(--accent); }
.ts-legend-swatch.str { border-radius: 4px; background: var(--str); }
.ts-takeaway { margin-top: 2.25rem; text-align: center; font-family: var(--display-font);
font-size: 1.05rem; font-style: italic; color: var(--ink); max-width: 540px; margin-left: auto;
margin-right: auto; line-height: 1.55; }
@media (max-width: 560px) {
.ts-hero-mid { max-width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
.ts-token { transition-duration: 0.001ms; }
.ts-token.blocked { animation: none; }
}
</style>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@500&family=Inter:wght@400;500&display=swap" rel="stylesheet">
<p class="ts-eyebrow">what is typescript</p>
<h2 class="ts-title">JavaScript, with a gate in front of it</h2>
<p class="ts-subtitle">You declare what type each value should be. A checkpoint enforces that before your code ever runs.</p>
<div class="ts-hero">
<div class="ts-filecard ts-src">
<svg class="ts-fileicon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/></svg>
<span class="ts-fileext">.ts</span>
<span class="ts-badge">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="m9 12 2 2 4-4"/></svg>
</span>
</div>
<div class="ts-hero-mid">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
<span>types get checked, then stripped away</span>
</div>
<div class="ts-filecard ts-out">
<svg class="ts-fileicon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/></svg>
<span class="ts-fileext">.js</span>
</div>
</div>
<div class="ts-legend">
<div class="ts-legend-item"><span class="ts-legend-swatch num"></span>a number, sent in correctly</div>
<div class="ts-legend-item"><span class="ts-legend-swatch str"></span>a string, sent where a number was expected</div>
</div>
<div class="ts-scene-block">
<div class="ts-scene-top">
<span class="ts-scene-name">Plain JavaScript</span>
<span class="ts-scene-tag">no gate</span>
</div>
<div class="ts-scene" id="jsScene">
<div class="ts-track-line"></div>
<div class="ts-token num" id="jsNum">123</div>
<div class="ts-token str" id="jsStr">"5"</div>
<div class="ts-endmark bug" id="jsBug">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20v-9"/><path d="M14 7a4 4 0 0 1 4 4v3a6 6 0 0 1-12 0v-3a4 4 0 0 1 4-4z"/><path d="M14.12 3.88 16 2"/><path d="M21 21a4 4 0 0 0-3.81-4"/><path d="M21 5a4 4 0 0 1-3.55 3.97"/><path d="M22 13h-4"/><path d="M3 21a4 4 0 0 1 3.81-4"/><path d="M3 5a4 4 0 0 0 3.55 3.97"/><path d="M6 13H2"/><path d="m8 2 1.88 1.88"/><path d="M9 7.13V6a3 3 0 1 1 6 0v1.13"/></svg>
</div>
</div>
<div class="ts-controls">
<button class="ts-btn" id="jsBtn" type="button">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="6 3 20 12 6 21 6 3"/></svg>
run
</button>
<p class="ts-note" id="jsNote">both values pass through untouched</p>
</div>
</div>
<div class="ts-scene-block">
<div class="ts-scene-top">
<span class="ts-scene-name">TypeScript</span>
<span class="ts-scene-tag">type gate</span>
</div>
<div class="ts-scene" id="tsScene">
<div class="ts-track-line"></div>
<div class="ts-token num" id="tsNum">123</div>
<div class="ts-token str" id="tsStr">"5"</div>
<div class="ts-gate" id="tsGate">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/></svg>
</div>
<div class="ts-endmark clean" id="tsClean">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>
</div>
</div>
<div class="ts-controls">
<button class="ts-btn" id="tsBtn" type="button">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="6 3 20 12 6 21 6 3"/></svg>
run
</button>
<p class="ts-note" id="tsNote">the number passes, the string gets stopped</p>
</div>
</div>
<p class="ts-takeaway">Same mismatch, two outcomes. JavaScript ships it and you find out later. TypeScript stops it at the gate, before it ever runs.</p>
<script>
(function () {
var wrapper = document.currentScript.closest('.infographic-ts')
|| document.querySelector('.infographic-ts');
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
var root = wrapper;
var TOKEN = 46;
var PAD = 14;
function layout() {
var jsScene = root.querySelector('#jsScene');
var tsScene = root.querySelector('#tsScene');
var jsW = jsScene.clientWidth;
var tsW = tsScene.clientWidth;
var jsNum = root.querySelector('#jsNum');
var jsStr = root.querySelector('#jsStr');
var jsBug = root.querySelector('#jsBug');
jsNum.dataset.start = PAD;
jsStr.dataset.start = PAD;
jsNum.dataset.end = jsW - TOKEN - PAD;
jsStr.dataset.end = jsW - TOKEN - PAD - 56;
jsNum.style.left = jsNum.dataset.start + 'px';
jsStr.style.left = jsStr.dataset.start + 'px';
jsBug.style.left = (jsW - PAD - 34) + 'px';
var tsNum = root.querySelector('#tsNum');
var tsStr = root.querySelector('#tsStr');
var tsGate = root.querySelector('#tsGate');
var tsClean = root.querySelector('#tsClean');
var gateX = tsW / 2;
tsNum.dataset.start = PAD;
tsStr.dataset.start = PAD;
tsNum.dataset.end = tsW - TOKEN - PAD;
tsStr.dataset.end = gateX - TOKEN - 10;
tsNum.style.left = tsNum.dataset.start + 'px';
tsStr.style.left = tsStr.dataset.start + 'px';
tsGate.style.left = gateX + 'px';
tsClean.style.left = (tsW - PAD - 34) + 'px';
}
layout();
window.addEventListener('resize', layout);
function reset(el) {
el.style.transition = 'none';
el.style.left = el.dataset.start + 'px';
el.classList.remove('blocked');
void el.offsetWidth;
el.style.transition = '';
}
var jsBtn = root.querySelector('#jsBtn');
var jsNum = root.querySelector('#jsNum');
var jsStr = root.querySelector('#jsStr');
var jsBug = root.querySelector('#jsBug');
var jsNote = root.querySelector('#jsNote');
jsBtn.addEventListener('click', function () {
reset(jsNum); reset(jsStr);
jsBug.classList.remove('show');
jsNote.classList.remove('err');
jsNote.textContent = 'sending values through\u2026';
requestAnimationFrame(function () {
jsNum.style.left = jsNum.dataset.end + 'px';
jsStr.style.left = jsStr.dataset.end + 'px';
});
setTimeout(function () {
jsBug.classList.add('show');
jsNote.classList.add('err');
jsNote.textContent = 'both got through \u2014 the mismatch quietly gives a wrong result later';
}, 1200);
});
var tsBtn = root.querySelector('#tsBtn');
var tsNum = root.querySelector('#tsNum');
var tsStr = root.querySelector('#tsStr');
var tsGate = root.querySelector('#tsGate');
var tsClean = root.querySelector('#tsClean');
var tsNote = root.querySelector('#tsNote');
tsBtn.addEventListener('click', function () {
reset(tsNum); reset(tsStr);
tsClean.classList.remove('show');
tsGate.classList.remove('ok', 'blocked');
tsNote.classList.remove('err', 'ok');
tsNote.textContent = 'sending values through\u2026';
requestAnimationFrame(function () {
tsNum.style.left = tsNum.dataset.end + 'px';
tsStr.style.left = tsStr.dataset.end + 'px';
});
setTimeout(function () {
tsClean.classList.add('show');
tsGate.classList.add('blocked');
tsStr.classList.add('blocked');
tsNote.classList.add('err');
tsNote.textContent = 'the number passed through \u2014 the string was rejected at the gate';
}, 1200);
});
})();
</script>
</div>