You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript枚举中实现泛型以优化键盘类代码

解决键盘按键状态管理中的代码重复问题

背景与初始困境

最近我在实现keydown事件的按键状态存储与校验功能时,为了区分不同类型的按键,定义了五个枚举标志:Alphabet、Modifier、Number、Navigation、Special,并把这些逻辑封装在了一个Keyboard类里。

这个类包含了每个枚举对应的get/set属性、一个set(key: string)方法,以及一系列isAlphabet()、isModifier()这类的判断方法——但很快我就发现,代码里充满了重复逻辑,完全违反了**DRY(Don't Repeat Yourself)**原则。比如每个枚举类型的getter/setter几乎是一模一样的模板,isXXX方法也只是换了个枚举类型的判断条件,维护起来特别麻烦。

泛型优化的尝试与卡点

我一开始想通过泛型来精简这些重复代码,但在把枚举类型和泛型语法结合的时候遇到了不少问题:比如怎么让泛型正确约束枚举的类型,怎么动态生成不同枚举对应的属性和方法,这些都没找到顺畅的实现方式,卡了好一阵子。

重构后的精简方案

后来我调整了思路,重新设计了这套逻辑,最终的重构方案完美解决了代码重复问题:

  1. 先定义一个统一的KeyType枚举来标识所有按键类型,替代原来的五个独立枚举:
enum KeyType {
  Alphabet,
  Modifier,
  Number,
  Navigation,
  Special
}
  1. 用Keys枚举存储所有按键值,配合一个KeyMap数组来映射按键与对应类型的关系:
enum Keys {
  A = 'a',
  Ctrl = 'Control',
  // ... 其他按键枚举值
}

const KeyMap: { key: Keys; type: KeyType }[] = [
  { key: Keys.A, type: KeyType.Alphabet },
  { key: Keys.Ctrl, type: KeyType.Modifier },
  // ... 其他按键与类型的映射关系
];
  1. 用泛型IFlag接口约束状态标志的结构,再封装一个通用的FlagContainer类来处理状态的设置与判断:
interface IFlag<T> {
  [key: string]: T;
}

class FlagContainer<T extends KeyType> {
  private flags: IFlag<boolean> = {};

  set(key: string, type: T) {
    const match = KeyMap.find(item => item.key === key && item.type === type);
    if (match) {
      this.flags[key] = true;
    }
  }

  is(type: T, key: string): boolean {
    const match = KeyMap.find(item => item.key === key && item.type === type);
    return !!match && this.flags[key] === true;
  }

  getFlags(type: T): IFlag<boolean> {
    return Object.fromEntries(
      Object.entries(this.flags).filter(([key]) => 
        KeyMap.some(item => item.key === key && item.type === type)
      )
    );
  }
}
  1. 最后只需要实例化FlagContainer并关联KeyType,就能得到精简后的Keyboard对象——原来的重复代码全部被通用逻辑替代了。

这种重构方式不仅消除了大量冗余代码,还让按键类型的扩展变得更简单:如果要新增一种按键类型,只需要在KeyType里加枚举值,补充KeyMap的映射即可,不需要修改容器类的核心逻辑。

内容的提问来源于stack exchange,提问作者zwoolli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 18:40:37