Search code examples
typescriptunity-game-enginegenericsecmascript-5typeguards

Trying to typeguard my custom event system in UnityTiny


I'm creating an event system in Unity Tiny because the one in the framework itself is very limited. I got it working but now I would like to make it more userfriendly for my colleagues. So I tried to typeguard it to prevent users from using different types but it does not seem to work for me. Any suggestions?

I already looked at these: - https://medium.com/ovrsea/checking-the-type-of-an-object-in-typescript-the-type-guards-24d98d9119b0 - https://dev.to/krumpet/generic-type-guard-in-typescript-258l

The problem is that unity tiny is using es5. So you can't get the object.construtor.name to get the name of a type. Therefor using "instanceof" isn't possible.

Also, the (object as T) does not work and I could not get the (object as T).type either.

export class Event<T> implements IEvent<T>{
        private handlers: {(data?: T): void}[] = [];
        public type : T;

        constructor(value: T){
            this.type = value;
        }


        public On(handler: { (data?: T): void }) : void {
            this.handlers.push(handler);
        }

        public Off(handler: { (data?: T): void }) : void {
            this.handlers = this.handlers.filter(h => h !== handler);
        }

        public Trigger(data?: T) {
            this.handlers.slice(0).forEach(h => h(data));
        }

        public Expose() : IEvent<T> {
            return this;
        }
    }
export class EventUtils {
        public static events = new Object();

        public static CreateEvent<T>(eventEntity: ut.Entity, nameOfEvent: string) : void{
            this.events[nameOfEvent] = new game.Event<T>();
        }

        public static Subscribe<T>(nameOfEvent: string, handeler: {(data? : T): void}) : void{
            //Loop through events object, look for nameOfEvent, use checkEventType() to check if it is the same type as given generic, then subscribe if true.
        }

        public static Trigger<T>(nameOfEvent: string, parameter?: T) : void{
            //Loop through events object, look for nameOfEvent, use checkEventType() to check if it is the same type as given generic, then trigger if true.
        }

        private static checkEventType<T>(object: any) : object is Event<T>{
            let temp : T;
            let temp2 = {temp};

            if (object.type instanceof temp2.constructor.name) {
                return true;
            }
            return false;
        }
    }
}
private static checkEventType<T>(object: any) : object is Event<T>{
            let temp : T;

            if (object.type as typeof temp) {
                return true;
                //always returns true even if the type is different
            }
            return false;
        }
    }

and

let temp : T;

            if ((object.type as typeof temp).type) {
                return true;
                //property 'type' does not exist in 'T'  
            }
            return false;

Solution

  • instanceof exists and has been supported for a while so you can use it even in ES5.

    The only problem is the way you are doing your check. If you need to check for an instance of a class you need to actually have the class (not just the type) in the checkEventType function:

    public static checkEventType<T>(cls: new (...a: any[]) => T, object: any): object is Event<T> {
        if (object.type instanceof cls) {
            return true;
        }
        return false;
    }
    

    Play