Skip to content

Instantly share code, notes, and snippets.

@magoz
Created January 25, 2025 10:44
Show Gist options
  • Save magoz/ea431d0422accb372daa946fe12d8b34 to your computer and use it in GitHub Desktop.
Save magoz/ea431d0422accb372daa946fe12d8b34 to your computer and use it in GitHub Desktop.
Narrowing Error and Result
type User = {
id: string
name: string
}
// This works because error is an Error. Internally, object is a non-primitive type (it's a class instance),
// and TypeScript can use it as a reliable discriminant.
// When you check if (r.error), TypeScript knows that an Error object is always truthy,
// making it a reliable way to narrow the type.
const narrowWithError = (id?: string) => {
if (!id) return { error: new Error('error message') }
return { result: { id, name: 'user name' } }
}
const runNarrowWithError = () => {
const r = narrowWithError('123')
if (r.error) {
return
}
console.log(r.result) // result is User
}
// This doesn't work as well because a string can be empty ('') which is falsy,
// so TypeScript can't use it as a reliable discriminant.
// When you check if (r.error), TypeScript can't be 100% sure about the type narrowing because strings can be falsy.
const narrowWithString = (id?: string) => {
if (!id) return { error: 'error message' }
return { result: { id, name: 'user name' } }
}
const runNarrowWithString = () => {
const r = narrowWithString('123')
if (r.error) {
return
}
console.log(r.result) // result is User | undefined
// Explicit type checking allows TypeScript to narrow the type correctly
const r2 = narrowWithString('123')
if (r2.error !== undefined) {
return
}
console.log(r2.result) // result is User
// Destructuring works too!
const { error, result } = narrowWithString('123')
if (error !== undefined) {
return
}
console.log(result) // result is User
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment