为什么 instanceof 在 Typescript 中没有按预期工作?
Why is instanceof not working as expected in Typescript?
所以我有这些 类 用于处理不同场景中的错误,如下所示:
export class APIError extends Error {
public readonly statusCode: number;
public readonly message: string;
constructor(statusCode?: number, message?: string) {
super(message);
Object.setPrototypeOf(this, APIError.prototype);
if (typeof statusCode === 'string') {
message = statusCode;
statusCode = null;
}
this.statusCode = statusCode || 500;
this.message = message || 'Internal Server Error';
}
public toJSON(): JsonData {
return {
statusCode: this.statusCode,
message: this.message,
};
}
}
export class NotFound extends APIError {
constructor(message?: string) {
super(404, 'Not Found');
Object.setPrototypeOf(this, NotFound.prototype);
}
}
export class StreamNotFound extends NotFound {
constructor() {
super('Stream Not Found');
Object.setPrototypeOf(this, StreamNotFound.prototype);
}
}
然后我有这个更新抽象方法:
public update(id: string, updateThing: T): T {
if (!updateThing) return;
const thing: T = this.get(id);
if (!thing) {
throw new NotFound(`${this.displayName} could not be found.`);
}
....
在我的控制器中,我尝试捕获错误然后获取它的实例,如下所示:
} catch (e) {
const statusCode = (e instanceof StreamNotFound) ? 404 : null;
throw HttpController.handleError(e, statusCode);
}
但 statusCode 将始终 return 为 null,即使 streamNotFound 扩展了 NotFound,并且 Notfound 正被 Update 抽象方法使用。
如您所见,我在每个方法上都添加了 Object.setPrototypeOf(this, StreamNotFound.prototype);
,所以我想知道为什么它没有按预期工作?
子class 将始终是 instanceof
本身及其父 class 中的任何一个。然而,反之则不然:父 class 不是 instanceof
它的任何子 class。
在这个例子中,StreamNotFound instanceof NotFound === true
。但是,父 class 明确地 不是 instanceof
它的任何子 class。这里,NotFound instanceof StreamNotFound === false
.
在你的控制器中,你正在 throw
ing 一个 NotFound
的实例,它永远不会是 instanceof StreamNotFound
,因为它在原型链中比它的子 classes.
在下面的简化示例中,Bar
将 Foo
扩展为子 class,因此:
Foo instanceof Foo === true
Bar instanceof Foo === true
Bar instanceof Bar === true
Foo instanceof Bar === false
class Foo {
constructor() {
}
}
class Bar extends Foo {
constructor() {
super();
}
}
const obj1 = new Foo();
const obj2 = new Bar();
console.log("Bar instanceof Bar: " + (obj2 instanceof Bar));
console.log("Bar instanceof Foo: " + (obj2 instanceof Foo));
console.log("Foo instanceof Bar: " + (obj1 instanceof Bar));
所以我有这些 类 用于处理不同场景中的错误,如下所示:
export class APIError extends Error {
public readonly statusCode: number;
public readonly message: string;
constructor(statusCode?: number, message?: string) {
super(message);
Object.setPrototypeOf(this, APIError.prototype);
if (typeof statusCode === 'string') {
message = statusCode;
statusCode = null;
}
this.statusCode = statusCode || 500;
this.message = message || 'Internal Server Error';
}
public toJSON(): JsonData {
return {
statusCode: this.statusCode,
message: this.message,
};
}
}
export class NotFound extends APIError {
constructor(message?: string) {
super(404, 'Not Found');
Object.setPrototypeOf(this, NotFound.prototype);
}
}
export class StreamNotFound extends NotFound {
constructor() {
super('Stream Not Found');
Object.setPrototypeOf(this, StreamNotFound.prototype);
}
}
然后我有这个更新抽象方法:
public update(id: string, updateThing: T): T {
if (!updateThing) return;
const thing: T = this.get(id);
if (!thing) {
throw new NotFound(`${this.displayName} could not be found.`);
}
....
在我的控制器中,我尝试捕获错误然后获取它的实例,如下所示:
} catch (e) {
const statusCode = (e instanceof StreamNotFound) ? 404 : null;
throw HttpController.handleError(e, statusCode);
}
但 statusCode 将始终 return 为 null,即使 streamNotFound 扩展了 NotFound,并且 Notfound 正被 Update 抽象方法使用。
如您所见,我在每个方法上都添加了 Object.setPrototypeOf(this, StreamNotFound.prototype);
,所以我想知道为什么它没有按预期工作?
子class 将始终是 instanceof
本身及其父 class 中的任何一个。然而,反之则不然:父 class 不是 instanceof
它的任何子 class。
在这个例子中,StreamNotFound instanceof NotFound === true
。但是,父 class 明确地 不是 instanceof
它的任何子 class。这里,NotFound instanceof StreamNotFound === false
.
在你的控制器中,你正在 throw
ing 一个 NotFound
的实例,它永远不会是 instanceof StreamNotFound
,因为它在原型链中比它的子 classes.
在下面的简化示例中,Bar
将 Foo
扩展为子 class,因此:
Foo instanceof Foo === true
Bar instanceof Foo === true
Bar instanceof Bar === true
Foo instanceof Bar === false
class Foo {
constructor() {
}
}
class Bar extends Foo {
constructor() {
super();
}
}
const obj1 = new Foo();
const obj2 = new Bar();
console.log("Bar instanceof Bar: " + (obj2 instanceof Bar));
console.log("Bar instanceof Foo: " + (obj2 instanceof Foo));
console.log("Foo instanceof Bar: " + (obj1 instanceof Bar));