danbal
danbal

Reputation: 1531

Get a class (static) property from an instance

Updated question:

In a client-side app, I am implementing an event-handling system, similarly to how Redux works.
I define event types as subclasses of a custom Event class. All such subclasses have their own type static property.
I trigger an event by creating an instance of a subclass, and sending it to the main handler function. In this main handler, I want to use type to decide which specific handler to call.

Since an event is an instance of an Event subclass, I use event.constructor.type.
It compiles and works fine, but the IDE complains: Property 'type' does not exist on type 'Function' (I also marked it in the code example).

Shall I just ignore the message, or is there a better way to access that static property from an instance?

type State = {};

class Event {
    public static type: string;
}

class MouseMoveEvent extends Event {
    public static type = "MouseMoveEvent";
    constructor(public x: number, public y: number) {
        super();
    }
}

class KeypressEvent extends Event {
    public static type = "KeyPressEvent";
    constructor(public key: string) {
        super();
    }
}

function handleMouseMove(event: MouseMoveEvent, state: State): State {
    // return some new state
}

function handleKeyPress(event: KeyPressEvent, state: State): State {
    // return some new state
}

const handlerMap: { [type: string]: (event: Event, state: State) => State; } = {
    [MouseMoveEvent.type]: (event: Event, state: State) => handleMouseMove(event as MouseMoveEvent, state),
    [KeyPressEvent.type]: (event: Event, state: State) => handleKeyPress(event as KeyPressEvent, state)
    // etc.
};

// The main handler, it receives all triggered events, and decides which specific handler to call, based on the `type` property.
function handleEvent(event: Event, state: State): State {
    // the editor complains here
    return handlerMap[event.constructor.type](event, state);
}


Original question:

class BaseClass {
    public static type: string;
}

class SubClass1 extends BaseClass {
    public static type = "SubClass1";
}

class SubClass2 extends BaseClass {
    public static type = "SubClass2";
}

const map: {[type: string]: number} = {
    [SubClass1.type]: 1,
    [SubClass2.type]: 2
};

function getNumber(x: BaseClass): number {
    return map[x.constructor.type]; // complains here
}

const foo = new SubClass1();
console.log(getNumber(foo));

While this code compiles and works (console outputs "SubClass1"), the editor complains: Property 'type' does not exist on type 'Function'.

I tried it in Intellij Idea and the Typescript playground (www.typescriptlang.org/play). Shall I just ignore the editor message, or is there a better way to access that static property from an instance?

Upvotes: 2

Views: 1575

Answers (1)

Nitzan Tomer
Nitzan Tomer

Reputation: 164327

You can create a type for the BaseClass constructor:

interface BaseClassStatic {
    type: string;
    new (): BaseClass;
}

And then cast to it:

function getNumber(x: BaseClass): number {
    return map[(x.constructor as BaseClassStatic).type];
}

Upvotes: 3

Related Questions