Crash Courses · PhD
Type Guards & Narrowing
Write type-safe code by narrowing types at runtime through guards and discriminants.
11 min read+200 XP on completionCert: TypeScript Crash Course
Tap any word in the text below to start reading from there.
Type Guards & Narrowing
TypeScript narrows types based on control flow — inside a conditional, the type is automatically refined.
Built-in Guards
function process(value: string | number | null) {
if (value === null) { return }
if (typeof value === 'string') {
return value.toUpperCase() // value is string here
}
return value * 2 // value is number here
}instanceof Guard
try {
const res = await fetch(url)
return await res.text()
} catch (err) {
if (err instanceof Error) {
return `Error: ${err.message}` // err.message is typed
}
return 'Unknown error'
}in Operator Guard
interface Dog { bark(): void }
interface Cat { meow(): void }
type Pet = Dog | Cat
function makeNoise(pet: Pet) {
if ('bark' in pet) {
pet.bark() // TypeScript: pet is Dog
} else {
pet.meow() // TypeScript: pet is Cat
}
}Custom Type Predicate
function isUser(obj: unknown): obj is User {
return (
typeof obj === 'object' && obj !== null &&
'id' in obj && 'email' in obj
)
}
function processResponse(data: unknown) {
if (isUser(data)) {
console.log(data.email) // fully typed
}
}Assertion Functions
function assertDefined<T>(val: T | null | undefined, name: string): asserts val is T {
if (val == null) throw new Error(`${name} is required`)
}
function render(userId: string | null) {
assertDefined(userId, 'userId')
fetchUser(userId) // TypeScript: userId is string here
}Reading progress
0% read
In this module
Type Guard
Type Predicate
Assertion Function
in operator
0%