Instanceof operator and this.constructor.name showing parent class name even it is child class in typescipt.
I defined a class that extends default typescript error class
export default class ExpressError extends Error {
message: string;
status: number;
error_id: number;
no_db_store: boolean;
name = "ExpressError";
constructor(message: string, status: number, error_id = 0, no_db_store = true) {
super();
this.message = message;
this.status = status;
this.error_id = error_id;
this.no_db_store = no_db_store;
console.log('\n\n\n\nthis.constructor.name = ' + this.constructor.name); // prints "Error"
console.log('new.target.name = ' + new.target.name); // prints "ExpressError"
console.log('\n\n\n\n');
}
}
Whenever I throw a new ExpressError
and try to get the class name it shows "Error" not "ExpressError". Furthermore, it enters first else if. how can I know if I made throw new Error
vs throw new ExpressError
?
this is the code where I try to get the class name:
catch (e: unknown) {
let structured_error: {
[key: string]: string | undefined | number | boolean
} = {};
// this line prints "Error"
console.log(e.constructor.name)
// checking if this is a sequelize error
if (e instanceof UniqueConstraintError) {
structured_error = {
message: e.errors[0].message,
status: 403,
stack: e.stack,
};
}
// this is the matched condition
else if (e instanceof Error) {
structured_error = {
message: e.message,
stack: e.stack,
};
}
else if (e instanceof ExpressError) {
structured_error = {
message: e.message,
stack: e.stack,
status: e.status,
no_db_store: e.no_db_store
};
}
}
The order of your if
/else
statements is incorrect. You need to try to match the most specific type first, as an object that is an instance of ExpressError
is also an instance of Error
.
See the following example:
class ExpressError extends Error {
message: string;
status: number;
error_id: number;
no_db_store: boolean;
name = "ExpressError";
constructor(message: string, status: number, error_id = 0, no_db_store = true) {
super();
this.message = message;
this.status = status;
this.error_id = error_id;
this.no_db_store = no_db_store;
console.log('\n\n\n\nthis.constructor.name = ' + this.constructor.name);
console.log('new.target.name = ' + new.target.name);
console.log('\n\n\n\n');
}
}
function testError() {
try {
throw new ExpressError('message', 0);
} catch (e: any) {
console.log(e.constructor.name);
if (e instanceof ExpressError) {
console.log("Instance of ExpressError");
}
if (e instanceof Error) {
console.log("Instance of Error");
}
}
}
testError();
The rest of the behavior you describe I can't reproduce. The constructor name is correctly printed.