Как правило, подкласс может переопределять свойство (или метод) суперкласса, если свойство подкласса присваивается свойству родительского класса. Для метода с несколькими сигнатурами вызовов, я полагаю, что правило состоит в том, что каждая сигнатура вызова в суперклассе должна иметь соответствующую сигнатуру вызова в подклассе, которая может быть назначена ему. Это «присваиваемое» отношение немного мутное, потому что параметры сравниваются бивариантно .
Чтобы методы были совместимы в вашем случае, каждый класс должен повторно объявить все типы событий из суперклассов, а также общую сигнатуру вызова:
class Agent extends Events {
on(event: 'eventA', listener: (body: IAEvent) => void): this
on(event: 'eventB', listener: (body: IPayload<IBEvent>) => void):this;
on(event: 'eventC', listener: (body: ICEvent[]) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this {
return super.on(event, listener);
}
}
class MyAgent extends Agent {
on(event: 'eventA', listener: (body: IAEvent) => void): this
on(event: 'eventB', listener: (body: IPayload<IBEvent>) => void):this;
on(event: 'eventC', listener: (body: ICEvent[]) => void): this;
on(event: 'EventD', listener: (body: IEventD) => void):this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this {
return super.on(event, listener);
}
}
Вы можете немного сократить дублирование, определив интерфейс только для метода on
и расширив его:
interface EventsOn<This> {
(event: string | symbol, listener: (...args: any[]) => void): This;
}
class Events {
on(event: string | symbol, listener: (...args: any[]) => void): this {
// ...
return this;
}
}
interface AgentOn<This> extends EventsOn<This> {
(event: 'eventA', listener: (body: IAEvent) => void): This;
(event: 'eventB', listener: (body: IPayload<IBEvent>) => void):This;
(event: 'eventC', listener: (body: ICEvent[]) => void): This;
}
interface Agent {
on: AgentOn<this>;
}
class Agent extends Events { }
interface MyAgentOn<This> extends AgentOn<This> {
(event: 'EventD', listener: (body: IEventD) => void):This;
}
interface MyAgent {
on: MyAgentOn<this>;
}
class MyAgent extends Agent { }
(Когда вы объявляете интерфейс для типа функции с сигнатурами вызовов, расширение интерфейса, по-видимому, накапливает сигнатуры вызовов, тогда как при объявлении интерфейса с помощью метода on
расширение интерфейса, похоже, теряет сигнатуры вызовов из суперинтерфейс.)