1️⃣ any
Represents any type of value.
Disables type checking for that value — TypeScript won’t check or warn about what you do with it.
let value: any = 5;
value = "hello"; // OK
value = true; // OK
value.toUpperCase(); // No TS error — but might fail at runtime if not a string⚠ When to use?
When migrating JS code to TS gradually
When you truly don’t know what type it will be
💡 But generally avoid any because you lose type safety.
2️⃣ unknown
Also represents any value, BUT safer than any
You can’t do anything with an unknown value without first checking its type.
let input: unknown = "hello";
input.toUpperCase(); // ❌ Error
if (typeof input === "string") {
input.toUpperCase(); // ✅ OK after type check
}⚠ When to use?
When accepting input where the type is not known up front (e.g. API input)
When you want to force type checking before use
3️⃣ void
Represents the absence of a return value in a function.
function logMessage(message: string): void {
console.log(message);
}✅ The function returns nothing (undefined implicitly).
⚠ When to use?
As a return type for functions that don’t return anything.
💡 A variable of type void can only be assigned undefined (or null if --strictNullChecks is off):
let a: void = undefined;4️⃣ never
👉 Represents a value that never occurs.
👉 Used for:
Functions that throw errors
Functions with infinite loops
Exhaustiveness checks
function throwError(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {}
}✅ TypeScript knows code after calling such functions is unreachable.
⚠ When to use?
Return type of a function that never completes normally
Ensuring all cases in
switchstatements are handled
type Shape = "circle" | "square";
function getArea(shape: Shape): number {
switch (shape) {
case "circle": return 3.14;
case "square": return 4;
default:
const _exhaustiveCheck: never = shape; // Enforces all cases handled
return _exhaustiveCheck;
}
}<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-out: #d4d4d4;
--ed-muted: #8a8a8a;
--ed-ok: #4ec9b0;
--ed-err: #f14c4c;
--run-bg: #2e7d46;
--run-bg-hover: #35924f;
--tok-kw: #c586c0;
--tok-type: #4ec9b0;
--tok-str: #ce9178;
--tok-num: #b5cea8;
--tok-punc: #d4d4d4;
--tok-cmt: #808080;
--tok-var: #ffffff;
max-width: 680px;
margin: 0 auto;
box-sizing: border-box;
background: transparent;
font-family: var(--body-font);
}
.infographic-ts * { box-sizing: border-box; }
.ts-header { font-family: 'Georgia', 'Fraunces', serif; font-weight: 700;
font-size: 1.9rem; letter-spacing: 0.01em; color: inherit; text-align: center;
margin: 0 0 1.4rem; }
.tabs { display: flex; justify-content: center; gap: 4px; margin-bottom: 1.1rem; flex-wrap: wrap; }
.tab-btn { font-family: var(--body-font); font-size: 0.82rem; font-weight: 500;
background: #ffffff; color: #2563eb; border: 1px solid #2563eb; padding: 0.65rem 1rem;
cursor: pointer; border-radius: 8px; }
.tab-btn.active { background: #2563eb; color: #ffffff; }
.tab-btn:hover:not(.active) { background: #eef3ff; }
.tab-panel { display: none; background: var(--ed-bg); border-radius: 8px;
padding: 1.1rem; }
.tab-panel.active { display: block; }
.code-window { background: var(--ed-bg); border: 1px solid #2f2f2f; border-radius: 8px;
overflow: hidden; margin-bottom: 1rem; }
.code-window:last-child { margin-bottom: 0; }
.code-topbar { display: flex; align-items: center; justify-content: space-between;
padding: 0.5rem 0.75rem; background: var(--ed-bar); }
.code-dots { display: flex; gap: 6px; }
.code-dot { width: 9px; height: 9px; 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.74rem; 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.32rem 0.7rem; font-size: 0.74rem;
font-family: var(--body-font); font-weight: 500; cursor: pointer; }
.run-btn:hover { background: var(--run-bg-hover); }
.run-btn svg { width: 10px; height: 10px; }
.code-body { padding: 0.85rem 1.1rem; font-family: var(--mono-font); font-size: 0.8rem;
line-height: 1.65; color: var(--ed-out); white-space: pre; overflow-x: auto; }
.tok-kw { color: var(--tok-kw); }
.tok-type { color: var(--tok-type); }
.tok-str { color: var(--tok-str); }
.tok-num { color: var(--tok-num); }
.tok-punc { color: var(--tok-var); }
.tok-cmt { color: var(--tok-cmt); }
.tok-var { color: var(--tok-var); }
.tok-err { color: var(--ed-err); }
.console { padding: 0 1.1rem; max-height: 0; overflow: hidden; font-family: var(--mono-font);
font-size: 0.78rem; line-height: 1.65; transition: max-height 0.35s ease, padding 0.35s ease; }
.console.show { max-height: 260px; padding: 0 1.1rem 0.85rem; }
.console-line { color: var(--ed-out); }
.console-line.ok { color: var(--ed-ok); }
.console-line.err { color: var(--ed-err); }
.note-line { font-family: var(--body-font); font-size: 0.8rem; color: var(--ed-muted);
padding: 0 0.2rem; margin: 0; }
</style>
<h2 class="ts-header">any, unknown, void, never</h2>
<div class="tabs">
<button class="tab-btn active" data-tab="t1" type="button">any</button>
<button class="tab-btn" data-tab="t2" type="button">unknown</button>
<button class="tab-btn" data-tab="t3" type="button">void</button>
<button class="tab-btn" data-tab="t4" type="button">never</button>
</div>
<div class="tab-panel active" id="t1">
<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">any.ts</span>
<button class="run-btn" id="anyBtn" 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="tok-kw">let</span> <span class="tok-var">value</span><span class="tok-punc">:</span> <span class="tok-type">any</span> <span class="tok-punc">=</span> <span class="tok-num">5</span><span class="tok-punc">;</span>
<span class="tok-var">value</span> <span class="tok-punc">=</span> <span class="tok-str">"hello"</span><span class="tok-punc">;</span>
<span class="tok-var">value</span> <span class="tok-punc">=</span> <span class="tok-kw">true</span><span class="tok-punc">;</span>
<span class="tok-var">value</span><span class="tok-punc">.</span><span class="tok-var">toUpperCase</span><span class="tok-punc">();</span></div>
<div class="console" id="anyConsole"></div>
</div>
<p class="note-line">Disables type checking entirely — useful when migrating JS gradually, but you lose type safety.</p>
</div>
<div class="tab-panel" id="t2">
<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">unknown.ts</span>
<button class="run-btn" id="unkBtn" 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="tok-kw">let</span> <span class="tok-var">input</span><span class="tok-punc">:</span> <span class="tok-type">unknown</span> <span class="tok-punc">=</span> <span class="tok-str">"hello"</span><span class="tok-punc">;</span>
<span class="tok-var">input</span><span class="tok-punc">.</span><span class="tok-var">toUpperCase</span><span class="tok-punc">();</span>
<span class="tok-kw">if</span> <span class="tok-punc">(</span><span class="tok-kw">typeof</span> <span class="tok-var">input</span> <span class="tok-punc">===</span> <span class="tok-str">"string"</span><span class="tok-punc">)</span> <span class="tok-punc">{</span>
<span class="tok-var">input</span><span class="tok-punc">.</span><span class="tok-var">toUpperCase</span><span class="tok-punc">();</span>
<span class="tok-punc">}</span></div>
<div class="console" id="unkConsole"></div>
</div>
<p class="note-line">Just as open as any, but you must narrow the type before doing anything with the value.</p>
</div>
<div class="tab-panel" id="t3">
<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">void.ts</span>
<button class="run-btn" id="voidBtn" 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="tok-kw">function</span> <span class="tok-var">logMessage</span><span class="tok-punc">(</span><span class="tok-var">message</span><span class="tok-punc">:</span> <span class="tok-type">string</span><span class="tok-punc">):</span> <span class="tok-type">void</span> <span class="tok-punc">{</span>
<span class="tok-var">console</span><span class="tok-punc">.</span><span class="tok-var">log</span><span class="tok-punc">(</span><span class="tok-var">message</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-var">logMessage</span><span class="tok-punc">(</span><span class="tok-str">"Hi there"</span><span class="tok-punc">);</span>
<span class="tok-kw">let</span> <span class="tok-var">a</span><span class="tok-punc">:</span> <span class="tok-type">void</span> <span class="tok-punc">=</span> <span class="tok-kw">undefined</span><span class="tok-punc">;</span></div>
<div class="console" id="voidConsole"></div>
</div>
<p class="note-line">The return type for a function that returns nothing — the result is undefined.</p>
</div>
<div class="tab-panel" id="t4">
<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">never.ts</span>
<button class="run-btn" id="neverBtn" 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="tok-kw">function</span> <span class="tok-var">throwError</span><span class="tok-punc">(</span><span class="tok-var">message</span><span class="tok-punc">:</span> <span class="tok-type">string</span><span class="tok-punc">):</span> <span class="tok-type">never</span> <span class="tok-punc">{</span>
<span class="tok-kw">throw</span> <span class="tok-kw">new</span> <span class="tok-var">Error</span><span class="tok-punc">(</span><span class="tok-var">message</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-kw">function</span> <span class="tok-var">infiniteLoop</span><span class="tok-punc">():</span> <span class="tok-type">never</span> <span class="tok-punc">{</span>
<span class="tok-kw">while</span> <span class="tok-punc">(</span><span class="tok-kw">true</span><span class="tok-punc">)</span> <span class="tok-punc">{}</span>
<span class="tok-punc">}</span>
<span class="tok-var">throwError</span><span class="tok-punc">(</span><span class="tok-str">"Something went wrong"</span><span class="tok-punc">);</span></div>
<div class="console" id="neverConsole"></div>
</div>
<p class="note-line">A function marked never doesn't return at all — it either throws or runs forever.</p>
</div>
<script>
(function () {
var wrapper = document.currentScript.closest('.infographic-ts')
|| document.querySelector('.infographic-ts');
var root = wrapper;
var tabBtns = root.querySelectorAll('.tab-btn');
var panels = root.querySelectorAll('.tab-panel');
tabBtns.forEach(function (btn) {
btn.addEventListener('click', function () {
var target = btn.getAttribute('data-tab');
tabBtns.forEach(function (b) { b.classList.toggle('active', b === btn); });
panels.forEach(function (p) { p.classList.toggle('active', p.id === target); });
});
});
function line(consoleEl, cls, text) {
var el = document.createElement('div');
el.className = 'console-line ' + (cls || '');
el.textContent = text;
consoleEl.appendChild(el);
}
var anyBtn = root.querySelector('#anyBtn');
var anyConsole = root.querySelector('#anyConsole');
anyBtn.addEventListener('click', function () {
anyConsole.innerHTML = '';
anyConsole.classList.add('show');
line(anyConsole, '', 'value = 5 \u2192 no TS error');
line(anyConsole, '', 'value = "hello" \u2192 no TS error');
line(anyConsole, '', 'value = true \u2192 no TS error');
line(anyConsole, 'err', 'value.toUpperCase() \u2192 Runtime error: value.toUpperCase is not a function');
});
var unkBtn = root.querySelector('#unkBtn');
var unkConsole = root.querySelector('#unkConsole');
unkBtn.addEventListener('click', function () {
unkConsole.innerHTML = '';
unkConsole.classList.add('show');
line(unkConsole, 'err', "input.toUpperCase() \u2192 Error: Object is of type 'unknown'.");
line(unkConsole, 'ok', 'typeof input === "string" \u2192 true, narrowed');
line(unkConsole, 'ok', 'input.toUpperCase() \u2192 "HELLO"');
});
var voidBtn = root.querySelector('#voidBtn');
var voidConsole = root.querySelector('#voidConsole');
voidBtn.addEventListener('click', function () {
voidConsole.innerHTML = '';
voidConsole.classList.add('show');
line(voidConsole, 'ok', 'Hi there');
line(voidConsole, '', 'logMessage(...) returns \u2192 undefined');
line(voidConsole, '', 'a \u2192 undefined');
});
var neverBtn = root.querySelector('#neverBtn');
var neverConsole = root.querySelector('#neverConsole');
neverBtn.addEventListener('click', function () {
neverConsole.innerHTML = '';
neverConsole.classList.add('show');
line(neverConsole, 'err', 'Uncaught Error: Something went wrong');
line(neverConsole, '', 'infiniteLoop() was not run \u2014 it would never return');
});
})();
</script>
</div>📝 Summary table
Type | Meaning | Example use |
|---|---|---|
any | Anything, disables type checking | Dynamic or legacy JS values |
unknown | Anything, but requires checking before use | Safe external input |
void | No value returned |
|
never | Never returns / never happens | Functions that throw, infinite loops |