A type guard is a runtime check that narrows the type of a variable within a conditional block.
Without type guards, TypeScript might not know the exact type and will raise an error if you try to access a type-specific property or method.
✅ typeof Type Guard
Use typeof to check primitive types like "string", "number", "boolean", etc.
📌 Syntax
function printValue(value: string | number) {
if (typeof value === "string") {
console.log(value.toUpperCase()); // ✅ string methods available
} else {
console.log(value.toFixed(2)); // ✅ number methods available
}
}✅ Valid typeof checks:
"string""number""boolean""undefined""symbol""bigint""function""object"
✅ instanceof Type Guard
Used to check class-based objects.
class Car {
drive() {
console.log("Driving...");
}
}
class Boat {
sail() {
console.log("Sailing...");
}
}
function operate(vehicle: Car | Boat) {
if (vehicle instanceof Car) {
vehicle.drive(); // ✅ TypeScript now knows it's a Car
} else {
vehicle.sail(); // ✅ It's a Boat here
}
}✅ Best for checking custom classes (not interfaces).
✅ Custom Type Guards (User-Defined)
Write your own type guard function using a return type like:
value is SomeType🧠 Example:
type Dog = { kind: "dog"; bark: () => void };
type Cat = { kind: "cat"; meow: () => void };
type Animal = Dog | Cat;
function isDog(animal: Animal): animal is Dog {
return animal.kind === "dog";
}
function makeSound(animal: Animal) {
if (isDog(animal)) {
animal.bark(); // ✅ Safe to call
} else {
animal.meow(); // ✅ It's a cat
}
}🔍 Another Example with Property Checks:
function isStringArray(input: unknown): input is string[] {
return Array.isArray(input) && input.every(item => typeof item === "string");
}🧪 Bonus: in Operator
Used to check if a property exists in an object.
type Admin = { role: "admin"; level: number };
type User = { role: "user"; access: string };
type Person = Admin | User;
function showDetails(person: Person) {
if ("level" in person) {
console.log(`Admin Level: ${person.level}`);
} else {
console.log(`User Access: ${person.access}`);
}
}<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;
--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); }
.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); }
.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">Type guards</h2>
<div class="tabs">
<button class="tab-btn active" data-tab="t1" type="button">typeof</button>
<button class="tab-btn" data-tab="t2" type="button">instanceof</button>
<button class="tab-btn" data-tab="t3" type="button">Custom guards</button>
<button class="tab-btn" data-tab="t4" type="button">in operator</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">typeof.ts</span>
<button class="run-btn" id="typeofBtn" 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">printValue</span><span class="tok-punc">(</span><span class="tok-var">value</span><span class="tok-punc">:</span> <span class="tok-type">string</span> <span class="tok-punc">|</span> <span class="tok-type">number</span><span class="tok-punc">)</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">value</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">console</span><span class="tok-punc">.</span><span class="tok-var">log</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>
<span class="tok-punc">}</span> <span class="tok-kw">else</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">value</span><span class="tok-punc">.</span><span class="tok-var">toFixed</span><span class="tok-punc">(</span><span class="tok-num">2</span><span class="tok-punc">));</span>
<span class="tok-punc">}</span>
<span class="tok-punc">}</span>
<span class="tok-var">printValue</span><span class="tok-punc">(</span><span class="tok-str">"hello"</span><span class="tok-punc">);</span>
<span class="tok-var">printValue</span><span class="tok-punc">(</span><span class="tok-num">3.14159</span><span class="tok-punc">);</span></div>
<div class="console" id="typeofConsole"></div>
</div>
<p class="note-line">typeof narrows to a JS primitive kind — "string", "number", "boolean", "undefined", etc.</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">instanceof.ts</span>
<button class="run-btn" id="instBtn" 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">class</span> <span class="tok-type">Car</span> <span class="tok-punc">{</span>
<span class="tok-var">drive</span><span class="tok-punc">()</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-str">"Driving..."</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-punc">}</span>
<span class="tok-kw">class</span> <span class="tok-type">Boat</span> <span class="tok-punc">{</span>
<span class="tok-var">sail</span><span class="tok-punc">()</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-str">"Sailing..."</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-punc">}</span>
<span class="tok-kw">function</span> <span class="tok-var">operate</span><span class="tok-punc">(</span><span class="tok-var">vehicle</span><span class="tok-punc">:</span> <span class="tok-type">Car</span> <span class="tok-punc">|</span> <span class="tok-type">Boat</span><span class="tok-punc">)</span> <span class="tok-punc">{</span>
<span class="tok-kw">if</span> <span class="tok-punc">(</span><span class="tok-var">vehicle</span> <span class="tok-kw">instanceof</span> <span class="tok-type">Car</span><span class="tok-punc">)</span> <span class="tok-punc">{</span>
<span class="tok-var">vehicle</span><span class="tok-punc">.</span><span class="tok-var">drive</span><span class="tok-punc">();</span>
<span class="tok-punc">}</span> <span class="tok-kw">else</span> <span class="tok-punc">{</span>
<span class="tok-var">vehicle</span><span class="tok-punc">.</span><span class="tok-var">sail</span><span class="tok-punc">();</span>
<span class="tok-punc">}</span>
<span class="tok-punc">}</span>
<span class="tok-var">operate</span><span class="tok-punc">(</span><span class="tok-kw">new</span> <span class="tok-var">Car</span><span class="tok-punc">());</span>
<span class="tok-var">operate</span><span class="tok-punc">(</span><span class="tok-kw">new</span> <span class="tok-var">Boat</span><span class="tok-punc">());</span></div>
<div class="console" id="instConsole"></div>
</div>
<p class="note-line">instanceof checks the actual class an object was built from.</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">custom-guard.ts</span>
<button class="run-btn" id="guardBtn" 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">type</span> <span class="tok-type">Dog</span> <span class="tok-punc">=</span> <span class="tok-punc">{</span> <span class="tok-var">kind</span><span class="tok-punc">:</span> <span class="tok-str">"dog"</span><span class="tok-punc">;</span> <span class="tok-var">bark</span><span class="tok-punc">:</span> <span class="tok-punc">()</span> <span class="tok-punc">=></span> <span class="tok-type">void</span> <span class="tok-punc">};</span>
<span class="tok-kw">type</span> <span class="tok-type">Cat</span> <span class="tok-punc">=</span> <span class="tok-punc">{</span> <span class="tok-var">kind</span><span class="tok-punc">:</span> <span class="tok-str">"cat"</span><span class="tok-punc">;</span> <span class="tok-var">meow</span><span class="tok-punc">:</span> <span class="tok-punc">()</span> <span class="tok-punc">=></span> <span class="tok-type">void</span> <span class="tok-punc">};</span>
<span class="tok-kw">type</span> <span class="tok-type">Animal</span> <span class="tok-punc">=</span> <span class="tok-type">Dog</span> <span class="tok-punc">|</span> <span class="tok-type">Cat</span><span class="tok-punc">;</span>
<span class="tok-kw">function</span> <span class="tok-var">isDog</span><span class="tok-punc">(</span><span class="tok-var">animal</span><span class="tok-punc">:</span> <span class="tok-type">Animal</span><span class="tok-punc">):</span> <span class="tok-var">animal</span> <span class="tok-kw">is</span> <span class="tok-type">Dog</span> <span class="tok-punc">{</span>
<span class="tok-kw">return</span> <span class="tok-var">animal</span><span class="tok-punc">.</span><span class="tok-var">kind</span> <span class="tok-punc">===</span> <span class="tok-str">"dog"</span><span class="tok-punc">;</span>
<span class="tok-punc">}</span>
<span class="tok-kw">function</span> <span class="tok-var">makeSound</span><span class="tok-punc">(</span><span class="tok-var">animal</span><span class="tok-punc">:</span> <span class="tok-type">Animal</span><span class="tok-punc">)</span> <span class="tok-punc">{</span>
<span class="tok-kw">if</span> <span class="tok-punc">(</span><span class="tok-var">isDog</span><span class="tok-punc">(</span><span class="tok-var">animal</span><span class="tok-punc">))</span> <span class="tok-punc">{</span>
<span class="tok-var">animal</span><span class="tok-punc">.</span><span class="tok-var">bark</span><span class="tok-punc">();</span>
<span class="tok-punc">}</span> <span class="tok-kw">else</span> <span class="tok-punc">{</span>
<span class="tok-var">animal</span><span class="tok-punc">.</span><span class="tok-var">meow</span><span class="tok-punc">();</span>
<span class="tok-punc">}</span>
<span class="tok-punc">}</span>
<span class="tok-var">makeSound</span><span class="tok-punc">({</span> <span class="tok-var">kind</span><span class="tok-punc">:</span> <span class="tok-str">"dog"</span><span class="tok-punc">,</span> <span class="tok-var">bark</span><span class="tok-punc">:</span> <span class="tok-punc">()</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-str">"Woof!"</span><span class="tok-punc">)</span> <span class="tok-punc">});</span>
<span class="tok-var">makeSound</span><span class="tok-punc">({</span> <span class="tok-var">kind</span><span class="tok-punc">:</span> <span class="tok-str">"cat"</span><span class="tok-punc">,</span> <span class="tok-var">meow</span><span class="tok-punc">:</span> <span class="tok-punc">()</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-str">"Meow!"</span><span class="tok-punc">)</span> <span class="tok-punc">});</span></div>
<div class="console" id="guardConsole"></div>
</div>
<p class="note-line">animal is Dog tells TypeScript the return value itself narrows the type — not just a boolean.</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">in-operator.ts</span>
<button class="run-btn" id="inBtn" 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">type</span> <span class="tok-type">Admin</span> <span class="tok-punc">=</span> <span class="tok-punc">{</span> <span class="tok-var">role</span><span class="tok-punc">:</span> <span class="tok-str">"admin"</span><span class="tok-punc">;</span> <span class="tok-var">level</span><span class="tok-punc">:</span> <span class="tok-type">number</span> <span class="tok-punc">};</span>
<span class="tok-kw">type</span> <span class="tok-type">User</span> <span class="tok-punc">=</span> <span class="tok-punc">{</span> <span class="tok-var">role</span><span class="tok-punc">:</span> <span class="tok-str">"user"</span><span class="tok-punc">;</span> <span class="tok-var">access</span><span class="tok-punc">:</span> <span class="tok-type">string</span> <span class="tok-punc">};</span>
<span class="tok-kw">type</span> <span class="tok-type">Person</span> <span class="tok-punc">=</span> <span class="tok-type">Admin</span> <span class="tok-punc">|</span> <span class="tok-type">User</span><span class="tok-punc">;</span>
<span class="tok-kw">function</span> <span class="tok-var">showDetails</span><span class="tok-punc">(</span><span class="tok-var">person</span><span class="tok-punc">:</span> <span class="tok-type">Person</span><span class="tok-punc">)</span> <span class="tok-punc">{</span>
<span class="tok-kw">if</span> <span class="tok-punc">(</span><span class="tok-str">"level"</span> <span class="tok-kw">in</span> <span class="tok-var">person</span><span class="tok-punc">)</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-str">`Admin Level: ${</span><span class="tok-var">person</span><span class="tok-punc">.</span><span class="tok-var">level</span><span class="tok-str">}`</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span> <span class="tok-kw">else</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-str">`User Access: ${</span><span class="tok-var">person</span><span class="tok-punc">.</span><span class="tok-var">access</span><span class="tok-str">}`</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-punc">}</span>
<span class="tok-var">showDetails</span><span class="tok-punc">({</span> <span class="tok-var">role</span><span class="tok-punc">:</span> <span class="tok-str">"admin"</span><span class="tok-punc">,</span> <span class="tok-var">level</span><span class="tok-punc">:</span> <span class="tok-num">5</span> <span class="tok-punc">});</span>
<span class="tok-var">showDetails</span><span class="tok-punc">({</span> <span class="tok-var">role</span><span class="tok-punc">:</span> <span class="tok-str">"user"</span><span class="tok-punc">,</span> <span class="tok-var">access</span><span class="tok-punc">:</span> <span class="tok-str">"read-only"</span> <span class="tok-punc">});</span></div>
<div class="console" id="inConsole"></div>
</div>
<p class="note-line">"level" in person checks which shape the object actually has at runtime.</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);
}
function bind(id, consoleId, cb) {
var btn = root.querySelector('#' + id);
var c = root.querySelector('#' + consoleId);
btn.addEventListener('click', function () {
c.innerHTML = '';
c.classList.add('show');
cb(c);
setTimeout(function () {
c.scrollIntoView({ behavior: 'smooth', block: 'end' });
}, 50);
});
}
bind('typeofBtn', 'typeofConsole', function (c) {
line(c, 'ok', 'HELLO');
line(c, 'ok', '3.14');
});
bind('instBtn', 'instConsole', function (c) {
line(c, 'ok', 'Driving...');
line(c, 'ok', 'Sailing...');
});
bind('guardBtn', 'guardConsole', function (c) {
line(c, 'ok', 'Woof!');
line(c, 'ok', 'Meow!');
});
bind('inBtn', 'inConsole', function (c) {
line(c, 'ok', 'Admin Level: 5');
line(c, 'ok', 'User Access: read-only');
});
})();
</script>
</div>🧠 Summary
Type Guard | Works With | Example |
|---|---|---|
| Primitives |
|
| Classes |
|
Custom function | Any type (with logic) |
|
| Properties in objects |
|