Always use proper Error objects when throwing exceptions, maintain consistent error handling contracts, and ensure type safety in error scenarios. Avoid throwing primitive strings, mixing throw/return patterns, or unsafe type assertions on error objects.
Key principles:
throw new Error('message')
instead of throw 'message'
undefined
on failure, don’t throw insteaderror instanceof Error
) before accessing propertiesExample of problematic patterns:
// Bad: throwing string
throw `External error with reported id was not registered`
// Bad: inconsistent with function signature that returns undefined
lookupError(error: number): ErrorRecord | undefined {
if (!errorRecord) throw `External error with reported id was not registered`
return errorRecord
}
// Bad: unsafe destructuring from any
catch (e) {
const { message } = e // e is any, not type-safe
}
Example of improved patterns:
// Good: proper Error object
throw new Error('External error with reported id was not registered')
// Good: consistent with signature
lookupError(error: number): ErrorRecord | undefined {
const errorRecord = this.registeredErrors[error]
return errorRecord // returns undefined if not found
}
// Good: type-safe error handling
catch (error) {
if (error instanceof Error) {
return err(error.cause)
}
throw error
}
Enter the URL of a public GitHub repository