KnisterPeter / react-to-typescript-definitions

Create typescript definitions files (d.ts) from react components
MIT License
238 stars 15 forks source link

How to write props to work with react-to-typescript-definitions #453

Closed FDiskas closed 4 years ago

FDiskas commented 6 years ago

Currently this not works in typescripted project.

https://github.com/nfq-eta/react-router4-with-layouts/blob/59e8917c0ba183e7ab4c5e7fd210ea74ccc03696/src/index.jsx

import React from 'react';
import PropTypes from 'prop-types';
import { Route as ReactRoute } from 'react-router-dom';

export const Route = (initProps) => {
  const { component, layout, ...rest } = initProps;
  let routeComponent = props => React.createElement(component, props);

  if (layout) {
    routeComponent = props =>
      React.createElement(layout, props, React.createElement(component, props));
  }

  return <ReactRoute {...rest} render={routeComponent} />;
};

Route.propTypes = {
  layout: PropTypes.oneOfType([
    PropTypes.func,
    PropTypes.node,
  ]),
  component: PropTypes.oneOfType([
    PropTypes.func,
    PropTypes.node,
  ]).isRequired,
};

Route.defaultProps = {
  layout: [],
};

https://unpkg.com/react-router4-with-layouts@1.0.2/dist/index.d.ts

declare module 'react-router4-with-layouts' {
    export type RouteLayout = (...args: any[])=>any | React.ReactNode;

    export type RouteComponent = (...args: any[])=>any | React.ReactNode;

    export interface RouteProps {
        layout?: RouteLayout;
        component: RouteComponent;
    }

    export function Route(props: RouteProps): JSX.Element;

}

Got the error:

Error:(25, 28) TS2322: Type '{ path: "/demo"; component: typeof DemoPage; layout: typeof DefaultLayout; }' is not assignable to type 'IntrinsicAttributes & RouteProps'.
  Type '{ path: "/demo"; component: typeof DemoPage; layout: typeof DefaultLayout; }' is not assignable to type 'RouteProps'.
    Types of property 'layout' are incompatible.
      Type 'typeof DefaultLayout' is not assignable to type '((...args: any[]) => any) | undefined'.
        Type 'typeof DefaultLayout' is not assignable to type '(...args: any[]) => any'.
FDiskas commented 6 years ago

Working typescript version without a plugin :frowning:

import * as React from 'react';
import { Route as ReactRoute, RouteProps } from 'react-router-dom';

export interface IRouteProps {
    layout?: React.ComponentType<RouteProps> | React.ComponentType<any>;
    component: React.ComponentType<RouteProps> | React.ComponentType<any>;
}

export interface IRouteState {
}

export class Route extends React.Component<IRouteProps & RouteProps, IRouteState> {
    constructor(props: IRouteProps) {
        super(props);
    }

    render() {
        const { component, layout, ...rest } = this.props;
        let routeComponent = (props: any) => React.createElement(component, props);

        if (layout) {
            routeComponent = props =>
                React.createElement(layout, props, React.createElement(component, props));
        }

        return <ReactRoute {...rest} render={routeComponent} />;
    }
}
KnisterPeter commented 6 years ago

In your error message, there is a reference to a DefaultLayout. What is the declaration of it? Besides that, your working typescript interface isn't compatible to your prop-types:

export interface IRouteProps {
    layout?: React.ComponentType<RouteProps> | React.ComponentType<any>;
    component: React.ComponentType<RouteProps> | React.ComponentType<any>;
}
Route.propTypes = {
  layout: PropTypes.oneOfType([
    PropTypes.func,
    PropTypes.node,
  ]),
  component: PropTypes.oneOfType([
    PropTypes.func,
    PropTypes.node,
  ]).isRequired,
};
FDiskas commented 6 years ago

DefaultLayout its a component - not pure one. :ghost: example could be found here https://github.com/nfq-eta/react-router4-with-layouts/blob/59e8917c0ba183e7ab4c5e7fd210ea74ccc03696/example/src/App.js

KnisterPeter commented 6 years ago

I think this

Route.propTypes = {
  layout: PropTypes.oneOfType([
    PropTypes.func,
    PropTypes.node,
  ]),
  component: PropTypes.oneOfType([
    PropTypes.func,
    PropTypes.node,
  ]).isRequired,
};

should better be:

Route.propTypes = {
  layout: PropTypes.node,
  component: PropTypes.node,
};
FDiskas commented 6 years ago

Failed prop type: Invalid prop component supplied to Route$$1, expected a ReactNode

FDiskas commented 6 years ago

You can test it here https://stackblitz.com/edit/react-kdwyaq?embed=1&file=lib/Router.js

KnisterPeter commented 6 years ago

I will do so when I find a bit of time.

FDiskas commented 4 years ago

:wedding:

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

FDiskas commented 4 years ago

good one :D

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.