【问题标题】:define Map with T[K]用 T[K] 定义地图
【发布时间】:2018-01-21 11:09:53
【问题描述】:

我目前正处于从 JS 过渡到 TS 的过程中,无法完全理解 keyof。我找到了https://github.com/kimamula/TypeScript-definition-of-EventEmitter-with-keyof,现在我正在尝试实现它。在我打开“noImplicitAny”之前一切都很好。

我在 ts 操场上创建了一个example 来显示我遇到的问题:

在构造函数中,无法访问K,因此我必须明确地创建地图(arg: any) 才能使其工作。

有没有在创建地图时避免使用 any 的解决方案?

【问题讨论】:

    标签: typescript es6-map keyof


    【解决方案1】:

    问题是您试图将(arg: keyof T) => any 分配给(arg: T[K]) => anykeyof T 代表T 的任意属性名例如在这个类中:

    class X { test: string; test2: number; }
    

    keyof X'test' | 'test2' 相同 而T[K]K extends keyof T 表示T 名称为K 的属性类型,因此对于T[K] 上面的类,可以是numberstring,具体取决于为@ 传递的值987654335@

    因此,如果您有Emitter<X>,您基本上会尝试将(arg: string | number) => any 分配给(arg: 'test' | 'test2') => any,这绝对不是类型安全的。

    我的猜测是,您希望将 listener 约束为具有与类成员相同的属性类型的参数。为此,您应该使用Map<string, ((arg: T[keyof T]) => any) []>arg 限制为T 的任何可能的属性类型

    class EventEmitter<T> {
    
      private events: Map<string, ((arg: T[keyof T]) => any) []>;
    
      constructor() {
        this.events = new Map<string, ((arg: T[keyof T]) => any) []>();
      }
    
      public getOrCreateEvents<K extends keyof T>(event: K, listener: (arg: T[K]) => any): ((arg: T[K]) => any) [] {
    
        return this.events.get(event) || this.events.set(event, new Array<(arg: T[K]) => any>()).get(event);
      }
    }
    
    // Test 
    class X { test: string; test2: number; }
    var d = new EventEmitter<X>();
    d.getOrCreateEvents("test2", c => console.log(c));// c is infered to string
    d.getOrCreateEvents("test2", c => console.log(c)); // c is infered to number
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-04
      • 2019-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-01
      相关资源
      最近更新 更多