Cristian E.
Cristian E.

Reputation: 3583

Typescript - Why implementation of the interface is not forced accordingly

I'm wondering why implementing twice same generic interface but with different parameters doesn't enforce the correct signatures in the derived class. The type of the generic parameter is omitted.

Please see sample:

interface IEvent { id: number; }
interface IHandle<T> {
  handle(event: T): void;
}

class EmailSentEvent implements IEvent {
  constructor(public id: number, public address: string) {}
}

class UserRegisteredEvent implements IEvent {
  constructor(public id: number) {}
}

class MailHandlerState implements 
  IHandle<EmailSentEvent>, 
  IHandle<UserRegisteredEvent> 
{
  // One implementation is enough to satisfy both interfaces
  handle = (event: EmailSentEvent): void => {

  };
}

Sandbox

Is there a way to enforce the implementation of both generic parameters? Thank you!

Upvotes: 4

Views: 1034

Answers (1)

Aleksey L.
Aleksey L.

Reputation: 37928

TLDR:

To make this work, change method notation

interface IHandle<T> {
    handle(event: T): void;
}

to property with a function type

interface IHandle<T> {
    handle: (event: T) => void;
}

Playground

** In this specific case implementation can still use method syntax


Turns out this works as intended:

--strictFunctionTypes mode in which function type parameter positions are checked contravariantly instead of bivariantly. The stricter checking applies to all function types, except those originating in method or construcor declarations. Methods are excluded specifically to ensure generic classes and interfaces (such as Array) continue to mostly relate covariantly. The impact of strictly checking methods would be a much bigger breaking change as a large number of generic types would become invariant (even so, we may continue to explore this stricter mode)

Source

Also in handbook

Upvotes: 2

Related Questions