Table of contents

  1. 1. Error TS1196
  2. 2. Type Guards
  3. 3. Type Predicate
  4. 4. Video Tutorial

By default, TypeScript’s compiler doesn’t allow you to add a custom type annotation to an error in a try-catch statement (TS1196). That’s because the underlying code can throw any type of error, even system generated exceptions, which makes it impossible for TypeScript to know the error type from the start. Luckily, there is the concept called “type guards“ which can help the TypeScript compiler to infer a specific type.

Error TS1196

TypeScript’s compiler will throw an error when you assign a custom type to an error in a catch block:

TS1196: Catch clause variable type annotation must be ‘any’ or ‘unknown’ if specified.

To circumvent the type annotation error, you can use a type guard.

Type Guards

A type guard is a runtime check which guarantees a type in a defined scope. There are different forms of type guards. The simplest type guard is a conditional block paired with an instanceof check:

1
2
3
4
5
6
7
8
9
10
function getNumber(something: string | number): number {
// Type guard with "typeof"
if (typeof something === 'string') {
// "something" is treated here as "string"
return parseInt(something, 10);
} else {
// "something" is treated here as "number"
return something;
}
}

Type Predicate

A more complex type guard is a function which returns a type predicate. A type predicate is identified by the is keyword. The following code shows type-safe error handling in action:

1
2
3
4
5
6
7
8
9
10
11
12
try {
// ...
} catch (error) {
// Type guard with "type predicate"
function isAxiosError(candidate: any): candidate is AxiosError {
return candidate.isAxiosError === true;
}

if (isAxiosError(error)) {
return processNotifications(error.response.data.notifications);
}
}

Video Tutorial

The following video shows how to use a type guard with an error object. This tip can be very useful when you want to work with the properties of an error: