Экспресс и Typescript - свойства Error.stack и Error.status не существуют

Я пытаюсь преобразовать существующий проект node.js из javascript в typescript. Я использовал ловушку ошибок 404 по умолчанию из шаблона Visual Studio Express 4:

// catch 404 and forward to error handler
app.use(function (req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

Однако я получаю следующее сообщение об ошибке: Свойство "status" не существует в типе "Ошибка".

Я получаю подобное сообщение, если попытаюсь вызвать свойство Error.stack: Свойство 'stack' не существует в типе 'Error'.

Кто-нибудь знает, что здесь происходит?

Изменить: Стив Фентон указывает, что я могу просто поместить статус ошибки в объект ответа. Однако мой механизм обработки ошибок использует двухэтапный процесс:

  • Создайте ошибку 404 и установите ее статус
  • Передайте его следующему родовому обработчику:

    app.use(function (err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: {}
        });
    });
    

Таким образом, состояние ошибки сначала устанавливается на объект Error, а затем возвращается обработчиком ошибок, чтобы решить, как обрабатывать ошибку.

Ответы

Ответ 1

Вы можете сказать TypeScript, что для вашего случая использования Error может быть status на нем:

interface Error{
    status?: number;
}

Итак, вы получаете:

interface Error{
    status?: number;
}

var err = new Error('Not Found');
err.status = 404;

Однако я должен сказать, что ваш экспресс-код не идиоматичен, но TypeScript может его понять, если вы расскажете об этом.

Ответ 2

Вы положили код ошибки в ответ...

app.use(function (req, res, next) {
    var err = new Error('Not Found');
    res.status(404)
    next(err);
});

Ответ 3

Лучший способ, по моему мнению, состоит в том, чтобы отключить проверки типов, установив ошибку на any или создав новый тип Error, поскольку он уже существует в @types/node.

Вместо этого вы должны расширить этот тип ошибки:

interface ResponseError extends Error {
  status?: number;
}

Ответ 4

import * as express from 'express';
interface Error {
  status?: number;
  message?: string;
}

app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: err
  });
});

Ответ 5

Обычно это вопрос о том, как лениво инициализировать объекты в Typescript.

Идеальный способ сделать это:

interface ErrorWithStatus extends Error {
    status: string
}

let foo = new Error() as ErrorWithStatus;
foo.status = '404';

Использование any или интерфейсов с обнуляемыми полями оставляет вас со слабыми и слабыми контрактами.

Ответ 6

Другой вариант в TypeScript:

let err: any;
err = new Error();
err.status = 404;

Ответ 7

Другой вариант в TypeScript:

const err: { status?: number, message:string } = new Error('Not Found');
err.status = 404;

Ответ 8

Я просто пошел за

var err = new Error('Not Found');
err['status'] = 404;