javascript - Why is instanceof not working as expected in Typescript? - Stack Overflow

So I have these classes that I use to handle errors in different scenerios like so:export class APIErr

So I have these classes that I use to handle errors in different scenerios like so:

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

And then I have this update abstract method:

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

In my controller, I'm trying to catch the error and then get it's instance like so:

} catch (e) {
            const statusCode = (e instanceof StreamNotFound) ? 404 : null;
            throw HttpController.handleError(e, statusCode);
        }

But statusCode will always return null, even though streamNotFound extends NotFound, and Notfound is being used by the Update abstract method.

As you can see, I'm adding the Object.setPrototypeOf(this, StreamNotFound.prototype); on each of the methods, so I'm wondering why it is not working as expected?

So I have these classes that I use to handle errors in different scenerios like so:

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

And then I have this update abstract method:

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

In my controller, I'm trying to catch the error and then get it's instance like so:

} catch (e) {
            const statusCode = (e instanceof StreamNotFound) ? 404 : null;
            throw HttpController.handleError(e, statusCode);
        }

But statusCode will always return null, even though streamNotFound extends NotFound, and Notfound is being used by the Update abstract method.

As you can see, I'm adding the Object.setPrototypeOf(this, StreamNotFound.prototype); on each of the methods, so I'm wondering why it is not working as expected?

Share Improve this question asked Jan 31, 2022 at 17:30 user8107351user8107351 4377 silver badges23 bronze badges 2
  • 1 You're thinking of inheritance in a reverse way: an instance of StreamNotFound is also an instance of NotFound, but an instance of a NotFound is not an instance of StreamNotFound. By the way: why on earth do you need those .setPrototypeOf()'s? classes set up their prototypes automatically. – FZs Commented Jan 31, 2022 at 17:40
  • If you're viewing this question, you probably would be more interested in this similar question – Zach Saucier Commented Aug 13, 2023 at 21:55
Add a ment  | 

2 Answers 2

Reset to default 6

A subclass will always be an instanceof itself and any of its parent classes. However, the reverse is not true: a parent class is not an instanceof any of its subclasses.

In this example, StreamNotFound instanceof NotFound === true. However, a parent class is explicitly not instanceof any of its subclasses. Here, NotFound instanceof StreamNotFound === false.

In your controller, you're throwing an instance of NotFound, which will never be an instanceof StreamNotFound, as it's further up in the prototype chain than its subclasses.


In the simplified example below, Bar extends Foo as a subclass, thus:

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

In my case, I had a root class of NodeCore with two classes that extended that class: Leaf and Choice. I was attempting to use a type that allowed either subclass:

type Node = Leaf | Choice;

Then I was attempting to check the instanceof that type:

if (node instanceof Node) { ... }

This doesn't work. But checking instanceof of the original class does work:

if (node instanceof NodeCore) { ... }

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745138108a4613299.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信