trusktr
trusktr

Reputation: 45454

How to explicitly define the return type of a generic returned class in TypeScript?

I have code like this:

import * as events from 'events' // Node.js events module

// my own version of EventEmitter with better typing
interface IEventEmitter<EventTypes> { /* ... */ }

// eslint-disable-next-line typescript/explicit-function-return-type
export function EventEmitter<EventTypes>() {
  // merge the IEventEmitter interface and EventEmitter as IEventEmitter
  // implementation into one.
  // XXX Is there a better way?
  return class NewEventEmitter
    extends ((events.EventEmitter as unknown) as IEventEmitter<EventTypes>)
    implements IEventEmitter<EventTypes> {}
}

As you can see I disabled an eslint rule so that it doesn't complain that I haven't specified the return type, and I let the return type be inferred.

But, how would I write that return type?

EDIT: Here's a playground example that shows @KarolMajewski's answer isn't working for me. It says Cannot find name 'NewEventEmitter'. Did you mean 'NodeEventEmitter'?.

EDIT 2: @KarolMajewski's answer does indeed work. For it to work, the class has to be assigned to a local variable. Here's the playground example.

Upvotes: 2

Views: 1773

Answers (2)

Karol Majewski
Karol Majewski

Reputation: 25790

Between writing explicit return types and letting TypeScript infer their type, there is a third way:

import * as events from 'events';

interface IEventEmitter<EventTypes> { /* ... */ }

export function EventEmitter<EventTypes>(): typeof MyClass {
  const MyClass = class extends events.EventEmitter implements IEventEmitter<EventTypes> {};

  return MyClass;
}

Although it's a bit of a trick, and it requires what's called an unnecessary local variable. In this case, this variable (MyClass) is used only to read type from.

Upvotes: 1

suddjian
suddjian

Reputation: 2396

Declare the return type to be IEventEmitter<EventTypes>

function makeEventEmitterClass<EventTypes>(): IEventEmitter<EventTypes> {
  // merge the IEventEmitter interface and EventEmitter as IEventEmitter
  // implementation into one.
  return class NewEventEmitter
    extends ((NodeEventEmitter as unknown) as IEventEmitter<EventTypes>)
    implements IEventEmitter<EventTypes> {}
}

Upvotes: 0

Related Questions