Преобразование ассоциативного массива javascript в typescript

#javascript #typescript

#javascript #машинописный текст

Вопрос:

В одной из наших систем у нас есть много javascript, связанных с пользовательским интерфейсом, который обрабатывает действия меню и выглядит следующим образом

 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
    }
 

}

и это используется с switch / if cases like if(menuAction[actionName] === "edit profile")... , который затем вызывает menuActions[actionName].Action() .

Прямо сейчас мы переводим систему на TypeScript, что для нас в новинку, и я застрял на том, как мне лучше всего реорганизовать и преобразовать этот конкретный фрагмент кода.

Мне не нравится, как это делается с помощью javascript прямо сейчас, поэтому, если возможно, я хотел бы воспользоваться возможностью изменить его на что-то лучшее, выполняя преобразование в typescript.

Моя интуиция подсказывает, что у меня должна быть коллекция MenuAction экземпляров из класса, но я не уверен, как я буду это реализовывать, а затем использовать.

Должен ли я полностью отказаться от использования класса и вместо этого просто использовать обычные объекты в массиве?

(Возможно, полезно знать, что это код для контроллера представления Angular 1.X).

Комментарии:

1. Я знаю, что спрашивал об этом в своем ответе, но в нынешнем виде ваш пример не является допустимым javascript. Это похоже на ассоциативный массив, но они реализованы базовыми объектами, а не массивами. Рассмотрите возможность редактирования вашего примера (и, возможно, обновления заголовка), чтобы ваш js был действительным.

Ответ №1:

Что касается ввода, это один из способов, которым вы могли бы это сделать:

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

Использовать экземпляры класса или нет — решать вам, TS совершенно не зависит от подобных вариантов дизайна.

… и если вы хотите, чтобы тип можно было использовать для классов implement , вместо этого вы должны определить его как интерфейс. На самом деле нет никакой другой разницы между пользовательским типом (псевдонимом типа) и интерфейсом.

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

Комментарии:

1. Я никогда не думал о введении нового типа. Это именно то, что я имел в виду в первую очередь, но не смог достичь самостоятельно! Я обязательно попробую, спасибо!

2. @DanielB О, кстати, в вашем примере у вас был массив, который не соответствовал вашему json, поэтому я сделал вашу коллекцию объектом. Или вам действительно нужен массив?

3. Нет, это здорово!

4. В итоге я использовал это решение, потому что я мог бы приспособить его к своим конкретным ситуациям проще, чем использовать класс.

Ответ №2:

Как насчет чего-то подобного:

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

( 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);
});
}
» rel=»nofollow»>код на игровой площадке
)

Комментарии:

1. Чистый, простой и соответствует цели. Попробуйте это первым делом с утра!