简体   繁体   中英

Converting javascript associative array to typescript

In one of our systems, we have a lot of UI related javascript that handles menu actions and that look like below

var menuActions = {
    "edit-profile": {
        Title: "rs_edit_profile",
        Action: function(callback){
            //some logic here to handle the UI
        },
        HasPermission: true
    },
    "delete-profile": {
        Title: "rs_edit_profile",
        Action: function(callback){
            //some logic here to handle the UI
        },
        HasPermission: true
    },
    "create-profile": {
        Title: "rs_edit_profile",
        Action: function(callback){
            //some logic here to handle the UI
        },
        HasPermission: false
    }

}

and that is used with switch / if cases like if(menuAction[actionName] === "edit profile")... which then calls the menuActions[actionName].Action() .

We're converting the system to TypeScript right now, which is all new for us, and I'm stuck on how I best should re-organize and convert this specific piece of code.

I don't like how it's done with javascript right now, so if possible, I would like to take the opportunity to change it to something better while doing the conversion to typescript.

My intuition says I should have a collection of MenuAction instances from a class, but I'm not sure as to how I would implement that and then use it.

Should I completely omit the use of a class and instead just use normal objects in an array?

(It might help to know that this is code for an Angular 1.X view controller).

Just regarding the typing, this is one way you could do it:

type Action = {
    Title: string;
    Action: (cb: () => void) => void;
    HasPermission: boolean;
}

var menuActions: {[key:string]: Action} = {
    "edit-profile": {
        Title: "rs_edit_profile",
        Action: function (callback) {
            //some logic here to handle the UI
        },
        HasPermission: true
    },
    "delete-profile": {
        Title: "rs_edit_profile",
        Action: function (callback) {
            //some logic here to handle the UI
        },
        HasPermission: true
    },
    "create-profile": {
        Title: "rs_edit_profile",
        Action: function (callback) {
            //some logic here to handle the UI
        },
        HasPermission: false
    }
}

Whether or not to use class instances is up to you, TS is quite agnostic about design choices like that.

... and if you want the type to be usable for classes to implement , you have to define it as an interface instead. It's really no other difference between a custom type ( type alias ) and an interface.

interface Action {
    Title: string;
    Action: (cb: () => void) => void;
    HasPermission: boolean;
}

How about something like this:

class MenuAction {
    private id: string;
    private title: string;
    private hasPermission: boolean;
    private action: (cb: Function) => void;

    constructor(id: string, title: string, hasPermission: boolean, action: (cb: Function) => void) {
        this.id = id;
        this.title = title;
        this.hasPermission = hasPermission;
        this.action = action;
    }

    get Title() {
        return this.title;
    }

    get HasPermission() {
        return this.hasPermission;
    }

    get Action() {
        return this.action;
    }

    equals(id: string): boolean {
        return this.id === id;
    }
}

const actions = [
    new MenuAction("edit-profile", "rs_edit_profile", true, function(callback) {
        //some logic here to handle the UI
    }),
    new MenuAction("delete-profile", "rs_edit_profile", true, function(callback) {
        //some logic here to handle the UI
    }),
    new MenuAction("create-profile", "rs_edit_profile", false, function(callback) {
        //some logic here to handle the UI
    })
];

function execute(id: string, callback: Function) {
    actions.filter(action => action.equals(id)).forEach(action => {
        action.Action(callback);
    });
}

( code in playground )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM