Issue
In summary, is it possible to have an interface that declares some base properties, but does not restrict additional properties? This is my current situation:
I’m using the Flux pattern, which defines a generic dispatcher:
class Dispatcher<TPayload> {
dispatch(arg:TPayload):void { }
}
I then create a dispatcher with my own payload type, like this:
interface ActionPayload {
actionType: string
}
const dispatcher = new Dispatcher<ActionPayload>();
Now I have some action code that should dispatch a payload with some additional data, but the ActionPayload
interface only allows for actionType
. In other words, this code:
interface SomePayload extends ActionPayload {
someOtherData: any
}
class SomeActions {
doSomething():void {
dispatcher.dispatch({
actionType: "hello",
someOtherData: {}
})
}
}
Gives a compile-error because someOtherData
does not match the ActionPayload
interface. The issue is that many different “action” classes will re-use the same dispatcher, so while it’s someOtherData
here it might be anotherKindOfData
over there, and so on. At the moment, all I can do to accomodate this is use new Dispatcher<any>()
because different actions will be dispatched. All actions share a base ActionPayload
, though, so I was hoping to be able to constrain the type like new Dispatcher<extends ActionPayload>()
or something. Is something like that possible?
Solution
If you want ActionPayload
to accept any other property you can add an indexer:
interface ActionPayload {
actionType: string;
// Keys can be strings, numbers, or symbols.
// If you know it to be strings only, you can also restrict it to that.
// For the value you can use any or unknown,
// with unknown being the more defensive approach.
[x: string | number | symbol]: unknown;
}
Answered By – Sebastien
Answer Checked By – Jay B. (BugsFixing Admin)