What Is a Type Guard in TypeScript?
Learn what a TypeScript type guard is, how typeof, instanceof, and custom predicates narrow types safely, with real interview-ready code examples.
Expected Interview Answer
A type guard is a runtime check that TypeScript uses to narrow a broader type, such as a union or unknown, down to a more specific type within a conditional block, so the compiler lets you safely access members that only exist on that narrower type.
Common built-in guards include typeof for primitives, instanceof for class instances, the in operator for checking property existence, and equality checks against literal values. Beyond these, developers write custom type guards as functions whose return type is a predicate in the form 'parameter is Type', which TypeScript trusts to narrow the argument's type in every branch where the function returns true. Type guards are essential whenever data arrives with a wide or unknown shape, such as API responses, discriminated unions, or third-party inputs, because they let you convert loosely typed data into precisely typed values without unsafe casts.
- Narrows unions and unknown into precise types safely
- Removes the need for unsafe type assertions
- Works with typeof, instanceof, in, and custom predicates
- Enables exhaustive handling of discriminated unions
- Improves autocomplete and catches property-access bugs early
AI Mentor Explanation
A type guard is like the third umpire reviewing a run-out on replay before confirming the decision — only after that specific check passes does the scorer treat the batter as definitely out rather than merely suspected. In the same way, code only treats a value as the narrower type once the guard's specific runtime check has actually confirmed it, not before.
Step-by-Step Explanation
Step 1
Built-in guards
typeof narrows primitives like string or number; instanceof narrows class instances; the in operator checks whether a property exists on an object.
Step 2
Discriminated unions
Comparing a shared literal 'kind' or 'type' property lets TypeScript narrow which member of a union you are working with.
Step 3
Custom type predicates
A function returning 'param is SomeType' tells the compiler to narrow the argument to SomeType wherever the function returns true.
Step 4
Narrowing scope
The narrowed type only applies within the block where the guard's condition holds true, not outside it.
Step 5
Replacing unsafe casts
Type guards validate shape at runtime, avoiding 'as SomeType' assertions that can lie to the compiler about untrusted data.
What Interviewer Expects
- Explains the difference between built-in and custom type guards
- Can write a user-defined type predicate function
- Knows how discriminated unions narrow via a literal property
- Understands guards operate at runtime, not just compile time
- Prefers guards over unsafe 'as' assertions for untrusted data
Common Mistakes
- Using 'as Type' assertions instead of writing a proper runtime guard
- Writing a type predicate function that lies about what it actually checks
- Forgetting that narrowing only applies inside the guarded block
- Confusing typeof narrowing with instanceof narrowing for objects vs primitives
Best Answer (HR Friendly)
“A type guard is a check in the code that confirms what kind of data you are actually working with before you use it, similar to verifying an ID before letting someone through a door. This lets developers safely handle data that could come in different shapes, such as a response from an API, without the program crashing from unexpected data.”
Code Example
interface Dog { kind: 'dog'; bark(): void }
interface Cat { kind: 'cat'; meow(): void }
type Pet = Dog | Cat;
function isDog(pet: Pet): pet is Dog {
return pet.kind === 'dog';
}
function greet(pet: Pet) {
if (isDog(pet)) {
pet.bark(); // narrowed to Dog here
} else {
pet.meow(); // narrowed to Cat here
}
}
function isString(value: unknown): value is string {
return typeof value === 'string';
}Follow-up Questions
- How do you write a custom type guard using a type predicate?
- What is the difference between typeof and instanceof narrowing?
- How do discriminated unions relate to type guards?
- Why is a type guard safer than an 'as' type assertion?
- Can a type guard narrow a value typed unknown into a specific interface?
MCQ Practice
1. What does a function with return type 'x is Foo' do?
A type predicate return type tells TypeScript to narrow the argument to the specified type in branches where the function returns true.
2. Which operator checks whether a property exists on an object for narrowing?
The in operator checks property existence and TypeScript can use it to narrow union types accordingly.
3. Why prefer a type guard over an 'as Type' assertion for untrusted data?
A type assertion does not verify anything at runtime; a type guard actually validates the shape before narrowing.
Flash Cards
What is a type guard? — A runtime check that lets TypeScript narrow a broader type to a more specific one within a conditional block.
What is a type predicate? — A function return type in the form 'param is Type' that tells the compiler to narrow param when the function returns true.
Name three built-in type guards. — typeof, instanceof, and the in operator.
Why avoid 'as Type' for untrusted input? — It performs no runtime check and can silently lie to the compiler, unlike a real type guard.