具有泛型类型的索引签名断言

时间:2021-05-03 03:04:53

标签: typescript generics types assertion

我正在构建一个自定义事件发射器,它接受描述可能事件的文字字符串类型作为通用类型来构建事件 -> 回调映射。当然我可以使用内置地图,但是来吧...

我想使用 [] 符号来更改列出的事件的键 我从这样的事情开始:

type FunctionDescriptor = {func: Function, args: any[]}
class EventEmitter<Events extends string> {
  [k in Events as string]?: FunctionDescriptor[]
  somemethods(event: Events) {
    this[event] = [...]
  }
}

事情是,首先:这行不通
第二:即使 [] 签名有效,我们也需要更改右侧以接受我们在类中需要的所有类型,从而破坏了类型检查的整个目的。
例如,类似:
let myEventMap = new EventEmitter<MyEvents>(); myEventMap["AnyKey"] = "AnyStuff"
有可能,这不是我想要的行为。
经过一段时间的修补,我想出了这个:

type FunctionDescriptor = {func: Function, args: any[]}

class EventMap<Events> {
  protected _: { [k in Events as string]?: FunctionDescriptor[] };
  // type asserted method call
  add(event: Events, callback: Function) {
    // example on how to access it
    this._[event].push(callback)
  }
}

我对打字稿很陌生,所以我真的不知道这对我的目标是否是一个好的模式解决方案,但对我来说它看起来符合我的目标:

<块引用>

a) 除了 bultin 函数之外,不能从外部分配任何东西;
b) 当您发出或添加事件时,所有事件都经过类型检查。
c) 很容易创建与某些 API 响应匹配的泛型类型。

我很惊讶这行得通。当你定义它时,我真的无法弄清楚 [] 里面的语法是什么。

对此有什么想法吗?

1 个答案:

答案 0 :(得分:0)

首先,如果您需要将 callback 添加到 events 数组,您应该将其键入为 FunctionDescriptor,因为这正是您在这里所期望的。

为了将 smth 添加到事件数组中,您需要确保 event 中存在 this.prop 属性

这是一个例子:

type Fn = (...args: any) => any

type FunctionDescriptor = { func: Fn, args: any[] }

type Data<T extends string> = {
    [P in T]: FunctionDescriptor[]
}

const isEvent = <T extends string>(prop: Partial<Data<T>>, event: T): prop is Partial<Data<T>> & Record<T, FunctionDescriptor[]> =>
    Object.prototype.hasOwnProperty.call(prop, event)

class EventMap<Events extends string> {
    protected prop: Partial<Data<Events>> = {};
    add(event: Events, callback: FunctionDescriptor) {
        if (isEvent(this.prop, event)) {
            this.prop[event].push(callback)
        }
    }
}

Playground

Here,在我的博客中,您可以找到有关输入事件的更多信息

相关问题