I'm building an error handling middleware for a node.js with express and TypeScript project. Within it I have a AppError class that extends Error. It looks like this:
class AppError extends Error {
public readonly internalCode: number | undefined;
public readonly httpCode: number;
public readonly message: string;
constructor(httpCode: number, message: string, internalCode?: number) {
super();
this.internalCode = internalCode;
this.message = message;
this.httpCode = httpCode;
}
public generateReport(): GenericReport {
return {
code: this.internalCode,
message: this.message,
};
}
}
I'm currently throwing new AppError() inside a /error route to catch it with the following middleware, errorHandler:
function errorHandler(err: Error, request: Request, response: Response, next: NextFunction,): Response {
if (err instanceof AppError) {
const report = err.generateReport();
return response.status(err.httpCode).json(report);
}
return response.status(500).json(err);
}
Inside the middleware I'm trying to find AppError on err [[Prototype]] chain, but the verification always fails in the TypeScript code. However, after transpiling it with Babel and running the JS version with node, err instanceof AppError resolves to true. Why doesn't it in the TS code?
In the example above, Object.getPrototypeOf(err) returns me Error {}, and changing err type to AppError or any doesn't affect the result.
To my understanding, the newly constructed object (after new AppError() runs) should be [[Prototype]]-linked to AppError. And running curl http://localhost:3333/error with the TS server on, I get { "internalCode": 1, "message": "This is an error", "httpCode": 500 }, which means that err is indeed created by AppError().
There's a working example of the problem in this GitHub repository. Any clarification on this topic will be greatly appreciated.
es5which is before classes where a thing.