Joel
Joel

Reputation: 23140

Express and Typescript - Error.stack and Error.status properties do not exist

I'm trying to convert an existing node.js project from javascript to typescript. I've been using the default 404 error catcher from the Visual Studio Express 4 template:

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

However, I'm getting the following error message: Property 'status' does not exist on type 'Error'.

I get a similar message if I try and invoke the Error's .stack property: Property 'stack' does not exist on type 'Error'.

Does anyone know what's going on here?

Edit: Steve Fenton points out that I could just put the error status on the response object. However, my error handling mechanism uses a two-step process:

  1. Create the 404 error and set its status
  2. Hand it on to the following generic handler:

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

So the error status is first set on the Error object, then read back by the error handler to decide how to handle the error.

Upvotes: 41

Views: 51246

Answers (8)

basarat
basarat

Reputation: 276085

Extend global Error

You can tell TypeScript that for your use case Error might have a status on it:

interface Error {
    status?: number;
}

So you get:

interface Error {
    status?: number;
}

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

Alternative

Put the status on the res and send the err. For Example:

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

Upvotes: 32

Rutger
Rutger

Reputation: 171

If I am not mistaken it is always best to get the type that is actually expected. I couldn't find any hard support that I am right, but I use:

import createError, { HttpError } from 'http-errors';

and to be complete for all types I also import the parameter types of use:

import express, { Request, Response, NextFunction } from 'express';

The actual function I use then looks like this:

app.use((err: HttpError, req: Request, res: Response, next: NextFunction) => { ... }

In your case if you want to create your own error:

app.use((req: Request, res: Response, next: NextFunction) => {
  next(createError(404));
});

or closer to your code:

app.use((req: Request, res: Response, next: NextFunction) => {
  let err = new HttpError('Not found');
  err.status = 404;
  next(err);
});

Upvotes: 8

dmwong2268
dmwong2268

Reputation: 3605

This is generally a question of how to lazily initialize objects in Typescript.

The ideal way to do this is:

interface ErrorWithStatus extends Error {
    status: string
}

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

Using any, or interfaces with nullable fields, leave you with subpar and weak contracts.

Upvotes: 8

kunl
kunl

Reputation: 311

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

Upvotes: 12

Fenton
Fenton

Reputation: 251022

You put the error code on the response...

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

Upvotes: 8

RaidenF
RaidenF

Reputation: 3531

The best way in my opinion, is not to disable type checks by setting the error to any, or creating a new Error type, since one already exists in @types/node.

Instead, you should extend that error type:

interface ResponseError extends Error {
  status?: number;
}

Upvotes: 30

Manu Artero
Manu Artero

Reputation: 10263

Another option in TypeScript:

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

Upvotes: 3

czechboy
czechboy

Reputation: 944

I just went for

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

Upvotes: 0

Related Questions