Definitelytyped: react-router: `withRouter` fails with `ComponentType` starting in 3.6.2

Created on 10 Sep 2019  ·  10Comments  ·  Source: DefinitelyTyped/DefinitelyTyped

This worked in 3.5.2, but fails in 3.6.2.

strict mode is disabled.

Is this a bug in the typings or TypeScript?

I added failing tests for this here: https://github.com/DefinitelyTyped/DefinitelyTyped/commit/f036856dfc9a7fd140f378402c102206738ec0a4.

import * as React from 'react';

// Copied from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/5db94ca7fd3570dc23588b404d7bb669a7886a8a/types/react-router/index.d.ts#L146
declare function withRouter<P, C extends React.ComponentType<P>>(
    component: C & React.ComponentType<P>,
): unknown;

declare const Component: React.ComponentType<{}>;
/*
Argument of type 'ComponentType<{}>' is not assignable to parameter of type 'ComponentClass<{}, any> | (ComponentClass<{}, any> & FunctionComponent<{}>)'.
  Type 'FunctionComponent<{}>' is not assignable to type 'ComponentClass<{}, any> | (ComponentClass<{}, any> & FunctionComponent<{}>)'.
    Type 'FunctionComponent<{}>' is not assignable to type 'ComponentClass<{}, any> & FunctionComponent<{}>'.
      Type 'FunctionComponent<{}>' is not assignable to type 'ComponentClass<{}, any>'.
        Type 'FunctionComponent<{}>' provides no match for the signature 'new (props: {}, context?: any): Component<{}, any, any>'.
*/
withRouter(Component);

If you know how to fix the issue, make a pull request instead.

  • [x] I tried using the @types/xxxx package and had problems.
  • [x] I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
  • [x] I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).
  • [x] [Mention](https://github.com/blog/821-mention-somebody-they-re-notified) the authors (see Definitions by: in index.d.ts) so they can respond.

    • Authors: @sergey-buturlakin @mrk21 @vasek17 @ngbrown @awendland @KostyaEsmukov @johnnyreilly @LKay @DovydasNavickas @huy-nguyen @grmiade @DaIgeb @egorshulga @rraina @pret-a-porter @t49tran @8enSmith @wezleytsai @eps1lon @HipsterBrown

If you do not mention the authors the issue will be ignored.

Bug

Most helpful comment

I'm still seeing issues even after this fix. Error message is something like

 Argument of type '({ myProp, history }: RouteComponentProps<{}, StaticContext, any> & { myProp: boolean; }) => Element' is not assignable to parameter of type 'ComponentType<RouteComponentProps<{}, StaticContext, any>>'.
  Type '({ myProp, history }: RouteComponentProps<{}, StaticContext, any> & { myProp: boolean; }) => Element' is not assignable to type 'FunctionComponent<RouteComponentProps<{}, StaticContext, any>>'.
    Types of parameters '__0' and 'props' are incompatible.
      Type 'PropsWithChildren<RouteComponentProps<{}, StaticContext, any>>' is not assignable to type 'RouteComponentProps<{}, StaticContext, any> & { myProp: boolean; }'.
        Property 'myProp' is missing in type 'RouteComponentProps<{}, StaticContext, any> & { children?: ReactNode; }' but required in type '{ myProp: boolean; }'.

with the component defined as

import { RouteComponentProps, withRouter } from "react-router-dom";

interface Props extends RouteComponentProps {
  myProp: boolean;
}

const Component = ({ myProp, match }: Props) => null

export default withRouter(Component);

I'm using

typescript: 3.6.3
@types/react-router: 5.0.4

All 10 comments

I won't have time to dig into this. I think we should just remove any usage of ComponentType and use plain functions with explicit props with regard to ref and children. ComponentType was always a bit problematic because of the union. If it didn't create errors it produced very large unions with other hocs. Library consumers shouldn't touch statics anyway so loosing those shouldn't be an issue.

Got the same issue. Already reported on the react-router repo (https://github.com/ReactTraining/react-router/issues/6906) but got redirected to here.

I'm still seeing issues even after this fix. Error message is something like

 Argument of type '({ myProp, history }: RouteComponentProps<{}, StaticContext, any> & { myProp: boolean; }) => Element' is not assignable to parameter of type 'ComponentType<RouteComponentProps<{}, StaticContext, any>>'.
  Type '({ myProp, history }: RouteComponentProps<{}, StaticContext, any> & { myProp: boolean; }) => Element' is not assignable to type 'FunctionComponent<RouteComponentProps<{}, StaticContext, any>>'.
    Types of parameters '__0' and 'props' are incompatible.
      Type 'PropsWithChildren<RouteComponentProps<{}, StaticContext, any>>' is not assignable to type 'RouteComponentProps<{}, StaticContext, any> & { myProp: boolean; }'.
        Property 'myProp' is missing in type 'RouteComponentProps<{}, StaticContext, any> & { children?: ReactNode; }' but required in type '{ myProp: boolean; }'.

with the component defined as

import { RouteComponentProps, withRouter } from "react-router-dom";

interface Props extends RouteComponentProps {
  myProp: boolean;
}

const Component = ({ myProp, match }: Props) => null

export default withRouter(Component);

I'm using

typescript: 3.6.3
@types/react-router: 5.0.4

@karol-majewski I am on TS 3.6.3 and the latest version @types/react-router: 5.0.4 is breaking, while returning to former is OK.

export function withRouter<P extends RouteComponentProps<any>, C extends React.ComponentType<P>>(
  component: C & React.ComponentType<P>,
): React.ComponentClass<Omit<P, keyof RouteComponentProps<any>> & WithRouterProps<C>> & WithRouterStatics<C>;

I encourage everyone to open new issues. If we fix your particular issue you have no way of being notified if you only comment in a closed thread. The typescript playground now allows configuring the ts version + config and is able to download type definitions. Including a link in a new issue helps maintainers a lot. Thank you :pray:

It seems like this only throws with strictFunctionTypes and I have a solution in mind. We'll see if it works out.

@sandersn Can we re-open this since the fix was reverted?

IIRC, @eps1lon discovered that this is due to a TypeScript bug: https://github.com/microsoft/TypeScript/issues/33490

Fix will come in: https://github.com/microsoft/TypeScript/pull/34607.

Works fine with the nightly version. Playground Link

typescript is a waste of time, I have spent hours trying to solve this stupid error and nothins, so if typescript is made to make life easier it is definately not doing the job, full of errors and bugs

This issue was fixed in TS 3.7. Closing.

Was this page helpful?
0 / 5 - 0 ratings