TypeScript:覆盖并修复包的类型定义

TypeScript: override and fix typing definitions for packages

我正在使用 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 ),我创建了一个自定义文件以将这些属性添加到界面。

但是,现在我遇到了一个问题:为事件定义的接口有一个名为 eventHandlers 的 属性 定义,但是它又缺少一个重要的定义,它是如何定义的:

export interface EventPropTypeInterface<TTarget, TEventKey> {
  /* other properties */,
  eventHandlers: {
    [key: string]:
      { (event: React.SyntheticEvent<any>): EventCallbackInterface<TTarget, TEventKey> } |
      { (event: React.SyntheticEvent<any>): EventCallbackInterface<TTarget, TEventKey>[] }
  }

但是,问题是该函数应该允许接受第二个参数,例如(我不确定第二个参数的类型,所以我 any):

{ (event: React.SyntheticEvent<any>, dataPoint: any): EventCallbackInterface<TTarget, TEventKey> }

因此,我尝试将此 属性 包含在我自己的定义中:

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>[] }
  }
}

但是现在,TypeScript 正在抱怨 @typings 目录中的 index.d.ts,说 eventHandlers 必须是我定义的类型。

有没有办法使用提供的类型定义文件并以某种方式"augment"它与我自己的定义类似,就像我在添加新属性时对其他接口所做的那样?

这可行。问题是类型的定义没有考虑可扩展性。

对象文字类型,例如 {x: string} 在许多情况下都很好,但不适用于复杂的嵌套结构。

原因是这些类型与类型别名类似,不受启用扩展性所需的声明合并的约束。

如果 eventHandlers 对象的可能值的类型被声明为 interface 它可以通过简单地添加额外的重载来轻松扩展。

下面的自包含示例展示了当类型被重构为对 eventHandlers 的值类型使用 interface 声明时,可扩展性是多么容易:

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> = {};
}

测试:

import victory = require("victory");

declare const handlerProps: victory.EventHandler<{}, {}>;

handlerProps({}, { x: 1, y: 2 }); // works fine

Here is a link to it in action

我强烈建议您向 https://github.com/DefinitelyTyped/DefinitelyTyped 提交合并请求,修改 npm:@types/victory 以这种方式使用 interface 以实现这种可扩展性。