5ar*_*5ar 17 typescript reactjs react-router
我正在使用从和导入类型的@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;
}
Run Code Online (Sandbox Code Playgroud)
引用的接口/类型的定义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;
}
Run Code Online (Sandbox Code Playgroud)
我想要的是扩展 Location 接口的 state 属性类型定义以包含自定义接口(即包含始终可用的属性)。所以像state: S & { A: string; B: string; }.
我曾尝试RouteComponentProps在模块声明中重新声明接口,react-router但我尝试的所有内容都会导致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<S>', but here has type 'any'.ts(2717)。
我还尝试Location在历史模块声明中重新声明接口,结果相同。之后我尝试LocationState在History命名空间内外重新声明类型,但这总是导致Duplicate identifier 'LocationState'.ts(2300).
除了为RouteComponentProps不同的名称编写自定义界面之外,我还能做些什么来获得所需的行为?我希望能够在项目中导入该接口,使用它扩展组件的 props 并具有可访问的属性A和B类型,props.location.state但也能够将任何其他属性视为any,而无需每次都传递类型变量定义。
所以基本上,你想要实现的目标被称为module augmentation. 由于无法更改现有属性的类型(出于明显的原因,它会破坏已经依赖于该属性的所有内容),因此唯一的方法是使用可保存自定义属性的新属性来扩充 Location 。
// global.d.ts
import { State, Key, Path } from "history"
declare module 'history' {
export interface Location<S extends State = State> extends Path {
state: S;
customState: { A: string; B: string; }
key: Key;
}
}
Run Code Online (Sandbox Code Playgroud)
因此,在添加这些属性时,如果您希望Location正确键入这些属性,则除了使用自定义属性之外别无选择。
您知道的另一个解决方案是创建一个您将在任何地方使用的新界面。
至少通过模块增强,即使您需要一个新属性,您也不必到处重新输入所有内容。
希望这个小小的解释能对您有所帮助。
干杯,