2

THE SCOPE:

Here is what I love about TypeScript:

interface CommandBus {
    emit(type: 'execute', payload: { command: string }) : number;
    emit(type: 'stop', payload: { pid: number }) : bool;
}

… and then, while I'm writing this commandBus.emit('stop', IntelliSense will tell me that the next function argument is payload: { pid: number }. This is priceless!

It is also possible to split it into several interfaces and TypeScript will merge it and the result will be the same:

interface CommandBus {
    emit(type: 'execute', payload: { command: string }) : number;
}

interface CommandBus {
    emit(type: 'stop', payload: { pid: number }) : bool;
}

This is what I use for my application. In different packages, I extend an interface with methods specific to that package. But the method signature is more complicated than the one above, and it has more common things, so I've created the generic:

interface IEmit<TType, TPayload> {
    (type: TType, id: string, options: { payload: TPayload }) : void
}

And I've tried to use it with my interface:

interface CommandBus {
    emit: IEmit<'execute', { command: string }>;
    emit: IEmit<'stop', { pid: number }>;
}

THE PROBLEM: TypeScript cannot handle this syntax, it only applies the first emit declaration and ignoring others.

THE QUESTION: How do I manage to overload a method in an interface using function types or interfaces?

1 Answer 1

2

Declaration merging can't change the type of an existing field (this is a design limitation). An alternate solution would be to declare a type for the emit field and extend that:

interface IEmit<TType, TPayload> {
    (type: TType, id: string, options: { payload: TPayload }) : void
}

interface CommandBus {
  emit: CommandBusEmit;
}

//default type for the emit field 
interface CommandBusEmit { }

//extensions to it 
interface CommandBusEmit extends IEmit<'execute', { command: string }> { }
interface CommandBusEmit extends IEmit<'stop', { pid: number }> { }

declare let cb: CommandBus;
cb.emit('execute', "", { payload : { command: ""}})
cb.emit('stop', "", { payload: { command: "" } }) // error
cb.emit('stop', "", { payload : { pid: 1}}) // ok
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.