Я использую TSLint для линтинга моего кода Angular TypeScript. Я включил правило no-unsafe-any, как кажется для меня хорошее правило - никогда ничего не предполагать о свойствах типа any.

Проблема в том, что правило сообщает об ошибках в некотором моем коде, которые я не могу исправить никаким другим способом, кроме отключения правила. Пример кода, который недействителен в соответствии с этим правилом ниже.

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);
      }),
    );
}

ЛИНТЕР сообщает о 4 ошибках в 2 строчках:

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'

Две проблемные строки:

  • if (error && error.status === httpCodeUnauthorized) {
  • const errorMessage = (error.error && error.error.message) || error.statusText;

Корень проблемы в том, что error аргумент обработчика, переданный {{ X1}} (библиотечная функция Rxjs) имеет тип any. Я понимаю, что error может быть любого типа, поэтому предполагать, что для него определены какие-либо свойства, небезопасно, но я сначала проверяю наличие этих свойств, прежде чем ссылаться на них, что кажется мне безопасным.

Что я могу / должен сделать, чтобы убедить компилятор линтера / TypeScript в его безопасности и передать правило?

2
Robert Kusznier 18 Сен 2018 в 12:15

2 ответа

Лучший ответ

В случае Angular ошибка всегда должна иметь тип HttpErrorResponse.

catchError((error: HttpErrorResponse) => {
//...
}

Тем не менее, в вашем коде вы просматриваете error.error, который определяется как any в HttpErrorResponse, поэтому вам, вероятно, следует использовать защиту типа для проверки и преобразования его в объект Error. Нет необходимости определять Error - он должен определяться базовыми типами машинописного текста.

function isError(value: any | undefined): value is Error {
  return error && ((error as Error).message !== undefined);
}

Затем использовать его в

const errorMessage = isError(error.error) ? error.error.message : error.statusText;
2
Jaan Oras 18 Сен 2018 в 09:58

У вас есть два варианта: если вы знаете , что error всегда имеет определенный тип, вы можете просто аннотировать этот тип. Если вы не уверены, вы можете использовать введите охранник.

Аннотация типа

С помощью аннотации типа вы можете просто сообщить компилятору, что вы ожидаете, что error будет определенного типа. Вы можете полностью избежать типа any с помощью этого подхода:

interface Error {
    status: string,
    statusText: string,
    error: { message: string | undefined } | undefined;
}

catchError((error: Error | undefined) => {
    //...
}

Тип охранник

Вы можете использовать защиту типа всякий раз, когда значение может иметь определенный тип, но не обязательно должно быть этого типа. Защитник типа проверит тип, и в следующем блоке переменная будет принадлежать к этому проверенному типу:

function isError(value: any | undefined): value is Error {
    return error && ((error as Error).status !== undefined);
}

catchError(error => {
    if (isError(error)) {
        //Inside this block, error will be of type Error
    }
}
1
Sefe 18 Сен 2018 в 09:37