V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
waiaan
V2EX  ›  Vue.js

请问 vue 的 defineEmits 类型如何使用动态键名

  •  
  •   waiaan · 3 天前 · 970 次点击
    enum BaseEvent {
      CLICK = 'click'
    }
    
    interface CustomEvent{
      [BaseEvent.CLICK]:string
    }
    
    defineEmits<EmitEvents>()
    
    

    上面这种写法 @vue/compiler-sfc 会报 Unsupported computed key in type referenced by a macro ,应该怎么写才对?谢谢。

    4 条回复    2025-09-01 09:44:08 +08:00
    murmur
        1
    murmur  
       3 天前
    换个思路,事件是双参数,第一个参数是你真的事件名字,后面是 args
    dssxzuxc
        2
    dssxzuxc  
       3 天前   ❤️ 2
    应该实现不了,defineXxxx 是编译器宏,会在编译阶段把 setup/props/emits/model 等展开转换成更低级的写法,如果是 TypeScript ,会在这个阶段进行类型检查并生成对应的运行时值。
    为了能在编译阶段做这件事,类型必须是静态的(虽然后面开始支持泛型了),不然编译器毛都找不到怎么给你转换成运行时值。
    另外建议不要在 Typescritp 用 enum ,绝大多数场景
    'a' | 'b' | 'c' 比
    enum BaseEvent {
    a = 'a',
    b = 'b',
    c = 'c',
    } 更好,还省去了一堆 import
    枚举唯一的好处就是改名不用重构,但这玩意谁没事会去改,经手过几个项目都是枚举用得飞起,我自己写的就完全不用。

    又试了下
    type Test = 'a' | 'b' | 'c'
    type CustomEvent = {
    [K in Test]: string
    }
    defineEmits<CustomEvent>()
    这样写是不会有警告的,说明编译器在编译阶段确实拿到了三个字面量,顺利生成代码。不过我懒得检查是否功能正常了,我不会写这种玩意,而且 eslint 会警告要改成 Record ,Record 写法无法通过编译。
    vitar
        3
    vitar  
       3 天前 via Android
    ts 配置现代搞得一点,启用 erasableSyntaxOnly 。不用 enum 就没问题了
    unhappy224
        4
    unhappy224  
       18 小时 42 分钟前
    const BaseEvent {
    CLICK : 'click'
    } as const

    试试这样呢?不过这样也算不上动态吧
    运行时动态也没啥意义,本来就是方便开发的
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   911 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 20:26 · PVG 04:26 · LAX 13:26 · JFK 16:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.