[react-router] Improve withRouter return type (#21329)

* [react-router] Improve withRouter return type

* Fix lint errors

* Fix dependencies version
This commit is contained in:
Jeremy Fauvel
2017-11-23 20:33:27 +01:00
committed by John Reilly
parent 6f16650b3d
commit 3289762cca
15 changed files with 30 additions and 45 deletions

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/svenanders/react-breadcrumbs
// Definitions by: Kostya Esmukov <https://github.com/KostyaEsmukov>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.4
import * as React from "react";
import * as ReactRouter from "react-router";

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/react-bootstrap/react-router-bootstrap
// Definitions by: Vincent Lesierse <https://github.com/vlesierse>, Karol Janyst <https://github.com/LKay>, Olmo del Corral <https://github.com/olmobrutall>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.4
export { default as LinkContainer } from "react-router-bootstrap/lib/LinkContainer"
export { default as IndexLinkContainer } from "react-router-bootstrap/lib/IndexLinkContainer"

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/ReactTraining/react-router/tree/master/packages/react-router-config
// Definitions by: François Nguyen <https://github.com/lith-light-g>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.4
import * as React from "react";
import { RouteComponentProps, match } from "react-router";

View File

@@ -3,7 +3,7 @@
// Definitions by: Tanguy Krotoff <https://github.com/tkrotoff>
// Huy Nguyen <https://github.com/huy-nguyen>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.4
import { match } from "react-router";
import * as React from 'react';

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/ReactTraining/react-router-native
// Definitions by: Eduard Zintz <https://github.com/ezintz>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.4
export {
match,

View File

@@ -15,7 +15,7 @@
// Daniel Roth <https://github.com/DaIgeb>
// Egor Shulga <https://github.com/egorshulga>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.4
import * as React from 'react';
import * as H from 'history';
@@ -99,7 +99,16 @@ export interface match<P> {
url: string;
}
// Diff / Omit taken from https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-311923766
export type Diff<T extends string, U extends string> = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T];
export type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>;
export function matchPath<P>(pathname: string, props: RouteProps): match<P> | null;
export function withRouter<P>(component: React.ComponentType<RouteComponentProps<any> & P>): React.ComponentClass<P>;
export function withRouter<P extends RouteComponentProps<any>>(component: React.ComponentType<P>): React.ComponentClass<Omit<P, keyof RouteComponentProps<any>>>;
// decorator signature
// There is a known issue in TypeScript, which doesn't allow decorators to change the signature of the classes
// they are decorating. Due to this, if you are using @withRouter decorator in your code,
// you will see a bunch of errors from TypeScript. The current workaround is to use withRouter() as a function call
// on a separate line instead of as a decorator.
export function withRouter<P, TFunction extends React.ComponentClass<P>>(target: TFunction): TFunction;

View File

@@ -1,13 +1,13 @@
import * as React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
interface TOwnProps {
interface TOwnProps extends RouteComponentProps<{}> {
username: string;
}
const Component = (props: TOwnProps & RouteComponentProps<{}>) => <h2>Welcome {props.username}</h2>;
const Component = (props: TOwnProps) => <h2>Welcome {props.username}</h2>;
const WithRouterComponent = withRouter<TOwnProps>(Component);
const WithRouterComponent = withRouter(Component);
const WithRouterTest = () => (<WithRouterComponent username="John" />);

View File

@@ -1,23 +0,0 @@
import * as React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
interface TOwnProps {
username: string;
}
// $ExpectType Component
@withRouter
class Component extends React.Component<TOwnProps> {
render() {
return (
<h2>Welcome {this.props.username}</h2>
);
}
}
const WithRouterTest = () => (<Component username="John" />);
// $ExpectType Element
WithRouterTest();
export default WithRouterTest;

View File

@@ -65,10 +65,10 @@ const PrivateRoute: React.SFC<RouteProps> = ({ component, ...rest }) => (
)}/>
);
const Public: React.SFC<RouteComponentProps<void>> = () => <h3>Public</h3>;
const Protected: React.SFC<RouteComponentProps<void>> = () => <h3>Protected</h3>;
const Public: React.SFC<RouteComponentProps<{}>> = () => <h3>Public</h3>;
const Protected: React.SFC<RouteComponentProps<{}>> = () => <h3>Protected</h3>;
class Login extends React.Component<RouteComponentProps<void>, {redirectToReferrer: boolean}> {
class Login extends React.Component<RouteComponentProps<{}>, {redirectToReferrer: boolean}> {
state = {
redirectToReferrer: false
};

View File

@@ -36,7 +36,7 @@ const About = () => (
</div>
);
const Topics: React.SFC<RouteComponentProps<void>> = ({ match }) => (
const Topics: React.SFC<RouteComponentProps<{}>> = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>

View File

@@ -16,7 +16,7 @@ import {
// are the same as before but now we see them inside a modal
// on top of the old screen.
class ModalSwitch extends React.Component<RouteComponentProps<void>> {
class ModalSwitch extends React.Component<RouteComponentProps<{}>> {
// We can pass a location to <Switch/> that will tell it to
// ignore the router's current location and use the location
// prop instead.
@@ -31,7 +31,7 @@ class ModalSwitch extends React.Component<RouteComponentProps<void>> {
// is still `/` even though its `/images/2`.
previousLocation = this.props.location;
componentWillUpdate(nextProps: RouteComponentProps<void>) {
componentWillUpdate(nextProps: RouteComponentProps<{}>) {
const { location } = this.props;
// set previousLocation if props.location is not modal
if (

View File

@@ -39,7 +39,7 @@ const Home = () => (
const WillMatch = () => <h3>Matched!</h3>;
const NoMatch: React.SFC<RouteComponentProps<void>> = ({ location }) => (
const NoMatch: React.SFC<RouteComponentProps<{}>> = ({ location }) => (
<div>
<h3>No match for <code>{location.pathname}</code></h3>
</div>

View File

@@ -17,7 +17,7 @@ const Main = () => <h2>Main</h2>;
const Sandwiches = () => <h2>Sandwiches</h2>;
interface PropsWithRoutes extends RouteComponentProps<void> {
interface PropsWithRoutes extends RouteComponentProps<{}> {
routes: MyRouteProps[];
}

View File

@@ -39,7 +39,6 @@
"test/MemoryRouter.tsx",
"test/Switch.tsx",
"test/InheritingRoute.tsx",
"test/WithRouter.tsx",
"test/WithRouterDecorator.tsx"
"test/WithRouter.tsx"
]
}
}

View File

@@ -2,7 +2,7 @@
// Project: https://github.com/pshrmn/rrc#readme
// Definitions by: Deividas Bakanas <https://github.com/DeividasBakanas>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
// TypeScript Version: 2.4
import * as React from "react";
import * as H from "history";