本文将提出一些建议关于js
开发者如何使用typescript
。
switch
语法在多个编程语言中经常使用。但是,作为一个前端开发者,我们会更希望使用对象遍历去查找。
为什么?有了switch
语句,我们就有了一个程序性的控制流,并且在每个情况下都不得不使用中断。如果我们可能忘记处理就可能会导致错误或意想不到的行为。
而对于对象遍历来说有更自然的控制流,更容易维护,也有更好的可读性。
handleAction(type: ActionType, task: Task): void {
switch(type) {
case ActionType.NEW_TASK:
this.taskService.createTask(task);
break;
case ActionType.EDIT_TASK:
this.taskService.editTask(task);
break;
case ActionType.REMOVE_TASK:
this.taskService.removeTask(task);
break;
case ActionType.COMPLETE_TASK:
this.taskService.completeTask(task);
break;
default:
throw Error(`handleAction: taskActionType ${type} is not supported`);
}
}
对象遍历查找会是更直观的方法。这些操作结构良好,更易于扩展。
handleAction(type: ActionType, task: Task): void {
const actions = <Record<ActionType, (task: Task) => Promise<void>>>{
[ActionType.NEW_TASK]: (task: Task) =>
this.taskService.createTask(task),
[ActionType.EDIT_TASK]: (task: Task) =>
this.taskService.editTask(task),
[ActionType.REMOVE_TASK]: (task: Task) =>
this.taskService.removeTask(task),
[ActionType.COMPLETE_TASK]: (task: Task) =>
this.taskService.completeTask(task),
};
if (actions[type]) {
void actions[type](task);
} else {
throw Error(`handleAction: taskActionType ${type} is not supported`);
}
}
我们都很熟悉js
中的map
方法:
const taskLabelMap = new Map([
[ActionType.NEW_TASK, 'Create Task'],
[ActionType.EDIT_TASK, 'Edit Task'],
[ActionType.REMOVE_TASK, 'Remove Task'],
[ActionType.COMPLETE_TASK, 'Complete Task'],
]);
在粗略看上面代码就是发现有点难以维护、定义。有时,开发人员忘记了在typescript
中定义map
有一种更简单的方法,即对象遍历。更自然的是使用给定的js
特点,而不是typescript
引入的数据结构。
const taskLabelMap1: {[key: string]: string} = {
[ActionType.NEW_TASK]: 'Create Task',
[ActionType.EDIT_TASK]: 'Edit Task',
[ActionType.REMOVE_TASK]: 'Remove Task',
[ActionType.COMPLETE_TASK]: 'Complete Task',
}
js中没有enum。
因此,使用enum
与使用对象相反。那么,有什么区别呢?enum
还有一些额外的功能。与对象相反,这些值不能被重新分配不同的值。
因此,为了类型安全,对象通常与enum
一起使用:
export enum ActionType {
NEW_TASK = 'new',
EDIT_TASK = 'edit',
REMOVE_TASK = 'remove',
COMPLETE_TASK = 'complete',
}
下面的示例使用了enum
的特性。这些值是类型安全的,但可能没有显式地将这些值与enum
一样使用。
const taskActions = <const>{
NEW_TASK: 'CREATE',
EDIT_TASK: 'EDIT',
REMOVE_TASK: 'REMOVE',
COMPLETE_TASK: 'COMPLETE',
};
type TASK_ACTIONS = (typeof taskActions)[keyof typeof taskActions];
因此,除枚举之外,最好的选择是结合类声明的联合类型。这些值是类型安全的,可以像引用枚举一样引用。
const newTask = ActionType.NEW_TASK
type TASK_ACTION = 'CREATE' | 'EDIT' | 'REMOVE' | 'COMPLETE';
export class TaskActions {
NEW_TASK: TASK_ACTION = 'CREATE';
EDIT_TASK: TASK_ACTION = 'EDIT';
REMOVE_TASK: TASK_ACTION = 'REMOVE';
COMPLETE_TASK: TASK_ACTION = 'COMPLETE';
}
在js
中有很多可以操作数组的方法。因此,每个前端开发人员都应该熟悉它们。然而,开发人员通常使用不同的方法来实现基本任务。在下面的示例中,应该检索具有特定类别的任务的数量。
我们可以使用for
循环,如下所示:
let taskHomeCount = 0;
for (const task of tasks) {
if (task.category === TaskCategroy.HOME) {
taskHomeCount += 1;
}
}
不过,作为js
开发者我们可以使用reduce
方法。reduce
可以很容易地将数组转换为所有类型的对象。这是一个非常强大的功能。
return taskHomeCount = tasks.reduce((result: number, task: Task) => {
return task.category === TaskCategory.HOME ? ++result : result;
}, 0);