#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;
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
})
];
Комментарии:
1. Чистый, простой и соответствует цели. Попробуйте это первым делом с утра!