【问题标题】:Typescript declaration merging to expand or override module type or interface property打字稿声明合并以扩展或覆盖模块类型或接口属性
【发布时间】:2023-03-18 22:46:01
【问题描述】:

我正在使用来自@types/react-router-dom 版本4.3.1 的类型,它从@types/react-router@types/history 导入类型。

在我的应用程序中,我总是有两个处于位置状态的属性,我希望它们自动从RouteComponentProps 接口中拉出,而不必每次都将自定义的LocationState 类型变量传递给接口。

 

RouteComponentProps接口的定义在react-router中,如下:

import * as H from 'history';

export interface RouteComponentProps<Params extends { [K in keyof Params]?: string } = {}, C extends StaticContext = StaticContext, S = H.LocationState> {
  history: H.History;
  location: H.Location<S>;
  match: match<Params>;
  staticContext?: C;
}

history 中引用的接口/类型的定义是:

export interface Location<S = LocationState> {
    pathname: Pathname;
    search: Search;
    state: S;
    hash: Hash;
    key?: LocationKey;
}

export type LocationState = History.LocationState;

export namespace History {
    export type LocationState = any;
}

 

我想要扩展 Location 接口的状态属性类型定义以包含自定义接口(即包含始终可用的属性)。比如state: S &amp; { A: string; B: string; }

 

我已尝试在 react-router 的模块声明中重新声明 RouteComponentProps 接口,但我尝试的所有操作都会导致 All declarations of 'RouteComponentProps' must have identical type parameters.ts(2428)Subsequent property declarations must have the same type. Property 'location' must be of type 'Location&lt;S&gt;', but here has type 'any'.ts(2717)

我还尝试在历史模块声明中重新声明Location 接口,结果相同。之后,我尝试在 Historynamespace 内部和外部重新声明 LocationState 类型,但这总是导致 Duplicate identifier 'LocationState'.ts(2300)

 

除了用不同的名称为RouteComponentProps 编写自定义界面之外,我还能做些什么来获得所需的行为?我希望能够在项目中导入该接口,用它扩展组件的 props 并具有可从 props.location.state 访问的属性的 AB 类型,但也能够将任何其他属性视为 any , 无需每次都传递类型变量定义

【问题讨论】:

  • 注意到这个问题得到了一些关注,所以只是评论说我没有找到用相同名称执行此操作的方法。我创建了一个类型 CustomRouteComponentProps&lt;P, C, S extends { A: string; B: string; }&gt; = RouteComponentProps&lt;Params, C, S&gt; 并在所有使用该类型的文件上查找和替换
  • 它没有回答问题,但我建议迁移到带有内置类型的 v5 并可能解决这些问题

标签: reactjs typescript react-router


【解决方案1】:

这可能不是您正在寻找的解决方案,但我通常有一个自定义位置界面(可能从您应用上的共享 .ts 文件中导出它),然后在该界面上使用 useLocation 挂钩。

import React, { ReactElement } from "react";
import { useLocation } from "react-router-dom";

interface CustomLocationState {
    A: string;
    B: string;
}

export default ():ReactElement => {
    const { state: {A, B} } = useLocation<CustomLocationState>();

    return <div>{A} - {B}</div>
}

【讨论】:

  • 正如 cmets 中提到的,自定义界面选项是我最终做的事情,我将自定义界面添加到 react-router-dom 模块。此外,这是一个预挂钩问题,因此此解决方案与版本不匹配,但位置的使用无关紧要 - 我只是想知道是否有办法覆盖现有接口。无论哪种方式,感谢您花时间回答这么老的问题:)
  • 很抱歉。刚刚意识到这是一个老问题。
猜你喜欢
  • 1970-01-01
  • 2019-01-06
  • 1970-01-01
  • 2019-05-28
  • 1970-01-01
  • 2021-02-26
  • 1970-01-01
  • 1970-01-01
  • 2019-04-17
相关资源
最近更新 更多