I'm using TSLint to lint my Angular TypeScript code. I enabled no-unsafe-any
rule, as it seems like a good rule to me to never assume anything about properties of type any
.
The problem is the rule reports errors on some of my code, which I'm unable to fix in any way other than disabling the rule. Example of a code that's invalid according to that rule below.
public intercept(request: HttpRequest<{}>, next: HttpHandler): Observable<HttpEvent<{}>> {
return next
.handle(request)
.pipe(
catchError(error => {
if (error && error.status === httpCodeUnauthorized) {
// Auto logout if unathorized
this.authenticationService.logout();
}
const errorMessage = (error.error && error.error.message) || error.statusText;
return throwError(errorMessage);
}),
);
}
Linter reports 4 errors on 2 lines:
ERROR: /home/robert/programming/npc/gui/src/app/core/authentication/unauthorized.interceptor.ts[24, 24]: Unsafe use of expression of type 'any'.
ERROR: /home/robert/programming/npc/gui/src/app/core/authentication/unauthorized.interceptor.ts[29, 33]: Unsafe use of expression of type 'any'.
ERROR: /home/robert/programming/npc/gui/src/app/core/authentication/unauthorized.interceptor.ts[29, 48]: Unsafe use of expression of type 'any'.
ERROR: /home/robert/programming/npc/gui/src/app/core/authentication/unauthorized.interceptor.ts[29, 72]: Unsafe use of expression of type 'any'
2 problematic lines are:
if (error && error.status === httpCodeUnauthorized) {
const errorMessage = (error.error && error.error.message) || error.statusText;
The root of the problem is that error
argument of a handler given to catchError
(Rxjs library function) has any
type. I understand error
can be of any type, so it's unsafe to assume it has any properties defined, but I'm first checking for the presence of those properties before actually refering to them, which seems safe to me.
What can/should I do to convince the linter/TypeScript compiler that it's safe and pass the rule?
In case of Angular the error should always be in of type HttpErrorResponse
catchError((error: HttpErrorResponse) => {
//...
}
That said, in your code you look into error.error
which is defined as any
in HttpErrorResponse
thus there you should probably use type guard to check and cast it to Error object. Not there is no need to define the Error
- it should be defined by typescript base types.
function isError(value: any | undefined): value is Error {
return error && ((error as Error).message !== undefined);
}
then use it in
const errorMessage = isError(error.error) ? error.error.message : error.statusText;