Why is the "typeof" the subclass of a generic class not assignable to the "typeof" the original class?

Viewed 183

I am trying to implement the "nanoevents" library in an extendable class.

You can look at the library's relevant type definitions here: https://github.com/ai/nanoevents/blob/128fac9/index.d.ts

// this is straight from the above link, only used as reference

interface EventsMap {
  [event: string]: any
}

interface DefaultEvents extends EventsMap {
  [event: string]: (...args: any) => void
}

// ...

export declare class Emitter<Events extends EventsMap = DefaultEvents> {
  // ...

   events: Partial<{ [E in keyof Events]: Events[E][] }>

  // ...

  on<K extends keyof Events> (this: this, event: K, cb: Events[K]): Unsubscribe

  // ...
}

I want to define my class as generic so that inheriting subclasses may define their relevant events and make use of the type checking.

import { createNanoEvents,Emitter,Unsubscribe } from "nanoevents";

class Extendable<Events extends {}={}>
{
  protected _emitter:Emitter<Events> = createNanoEvents<Events>();

  public on<E extends keyof Events>(event:E,callback:Events[E]):Unsubscribe
  {
    return this._emitter.on(event,callback);
  }
}

I have successfully extended my class here:

interface ExtendedEvents {
    'a':()=>void,
    'b':(c:number)=>void,
}

class Extended<Events extends ExtendedEvents=ExtendedEvents> extends Extendable<Events>
{
}

And now I want to pass it to the following function:

function foo(extendableType:typeof Extendable):void { /* ... */ }
foo(Extended); // <-- error here

Which fails with:

TS2345: Argument of type 'typeof Extended' is not assignable to type 'typeof Extendable'.
  Construct signature return types 'Extended<ExtendedEvents>' and 'Extendable<Events>' are incompatible.
    The types of '_emitter.events' are incompatible between these types.
      Type 'Partial<{ a: (() => void)[]; b: ((c: number) => void)[]; }>' is not assignable to type 'Partial<{ [E in keyof Events]: Events[E][]; }>'.
0 Answers
Related