MST

星途 面试题库

面试题:TypeScript枚举类型在复杂场景下的最佳实践

假设你正在开发一个前端应用,其中有一个状态机,状态之间存在复杂的转换关系。例如,状态`Draft`可以转换到`Submitted`和`Discarded`状态;`Submitted`可以转换到`Approved`、`Rejected`和`Returned`状态等。请使用TypeScript枚举类型来定义这些状态,并实现一个函数`canTransition`,该函数接受两个状态作为参数,判断是否可以从第一个状态转换到第二个状态,同时阐述在这种复杂场景下使用枚举类型的优缺点及替代方案。
20.0万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

定义状态枚举类型

enum State {
    Draft = 'Draft',
    Submitted = 'Submitted',
    Discarded = 'Discarded',
    Approved = 'Approved',
    Rejected = 'Rejected',
    Returned = 'Returned'
}

实现 canTransition 函数

function canTransition(from: State, to: State): boolean {
    const transitionRules: { [key in State]: State[] } = {
        [State.Draft]: [State.Submitted, State.Discarded],
        [State.Submitted]: [State.Approved, State.Rejected, State.Returned]
    };
    return transitionRules[from]?.includes(to) || false;
}

使用枚举类型的优点

  1. 类型安全:枚举类型提供了类型检查,减少错误发生的可能性。比如在 canTransition 函数中,传入的参数类型必须是定义好的枚举值,否则会报错。
  2. 可读性:使用有意义的枚举名称,比直接使用字符串或数字更具可读性。例如 State.Draft 比字符串 'Draft' 更能清晰表达其含义。
  3. 可维护性:当状态需要修改或扩展时,只需要在枚举定义中进行修改,而不需要在使用的地方逐个修改硬编码的值。

使用枚举类型的缺点

  1. 灵活性有限:枚举类型一旦定义,其值相对固定。如果需要动态生成状态,枚举就不太适用。
  2. 编译后代码体积:在编译成JavaScript后,枚举类型会生成额外的代码,可能会增加代码体积。

替代方案

  1. 对象字面量:可以使用对象字面量来定义状态。例如:
const state = {
    Draft: 'Draft',
    Submitted: 'Submitted',
    Discarded: 'Discarded',
    Approved: 'Approved',
    Rejected: 'Rejected',
    Returned: 'Returned'
};

优点是更灵活,可以动态添加或修改属性。缺点是类型安全性不如枚举,需要手动进行类型检查。 2. :可以使用类来封装状态和状态转换逻辑。例如:

class StateMachine {
    private states = {
        Draft: 'Draft',
        Submitted: 'Submitted',
        Discarded: 'Discarded',
        Approved: 'Approved',
        Rejected: 'Rejected',
        Returned: 'Returned'
    };
    canTransition(from: string, to: string): boolean {
        const transitionRules: { [key: string]: string[] } = {
            [this.states.Draft]: [this.states.Submitted, this.states.Discarded],
            [this.states.Submitted]: [this.states.Approved, this.states.Rejected, this.states.Returned]
        };
        return transitionRules[from]?.includes(to) || false;
    }
}

优点是可以封装更多的逻辑和行为,缺点是相对复杂,代码量可能会增加。