I'm using the React victory library for charts, and I'm using TypeScript. I have added the @types/victory package to my project, but unfortunately, it's missing a bunch of key definitions that I need. For some interfaces, it was missing a couple of properties, so (using this answer), I created a custom file to add those properties to the interfaces.
But, now I have a problem: the interface defined for events has a property named eventHandlers
defined, but again it's missing an important definition, how it's defined:
export interface EventPropTypeInterface<TTarget, TEventKey> {
/* other properties */,
eventHandlers: {
[key: string]:
{ (event: React.SyntheticEvent<any>): EventCallbackInterface<TTarget, TEventKey> } |
{ (event: React.SyntheticEvent<any>): EventCallbackInterface<TTarget, TEventKey>[] }
}
But, the problem is that the function should allow accepting a second parameter, example (I'm not sure about the type of the second argument, so I have any
):
{ (event: React.SyntheticEvent<any>, dataPoint: any): EventCallbackInterface<TTarget, TEventKey> }
So, I tried to include this property in my own definition:
declare module "victory" {
export interface EventPropTypeInterface<TTarget, TEventKey> {
eventHandlers: {
[key: string]:
{ (event: React.SyntheticEvent<any>, dataPoint: any): EventCallbackInterface<TTarget, TEventKey> } |
{ (event: React.SyntheticEvent<any>, dataPoint: any): EventCallbackInterface<TTarget, TEventKey>[] }
}
}
But now, TypeScript is complaining about the index.d.ts
in the @typings
directory, saying that eventHandlers
must be of the type I have defined.
Is there a way to use the provided type definition file and somehow "augment" it with my own definition similar to what I did with other interfaces when just adding new properties?
This can work. The problem is that the types were not defined with extensibility in mind.
Object literal types, such as {x: string}
are great in many situations, but not for complex nested structures.
The reason is that these types, similar to type aliases, are not subject to the declaration merging needed to enable extensibility.
If the types of the possible values of the eventHandlers
object were declared as an interface
it could be extended with ease by simply adding additional overloads.
The following, self contained example shows how extensibility is quite easy when the types are refactored to use an interface
declaration for the value type of eventHandlers
:
declare module "victory" {
interface EventHandler<TTarget, TEventKey> {
(event: React.SyntheticEvent<any>): EventCallbackInterface<TTarget, TEventKey>
(event: React.SyntheticEvent<any>): EventCallbackInterface<TTarget, TEventKey>[]
}
export interface EventPropTypeInterface<TTarget, TEventKey> {
eventHandlers: {
[key: string]: EventHandler<TTarget, TEventKey>
}
}
}
declare module "victory" {
// this interface merges with the original, declaring additional overloads of the all signature
interface EventHandler<TTarget, TEventKey> {
// declare overloads
(event: React.SyntheticEvent<any>, dataPoint: any): EventCallbackInterface<TTarget, TEventKey>
(event: React.SyntheticEvent<any>, dataPoint: any): EventCallbackInterface<TTarget, TEventKey>[]
}
}
type EventCallbackInterface<T, U> = {}
declare namespace React {
export type SyntheticEvent<T> = {};
}
Test:
import victory = require("victory");
declare const handlerProps: victory.EventHandler<{}, {}>;
handlerProps({}, { x: 1, y: 2 }); // works fine
Here is a link to it in action
I strongly recommend that you submit a Pull Request to https://github.com/DefinitelyTyped/DefinitelyTyped that modifies npm:@types/victory
to use an interface
in this manner to enable such extensibility.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With