import { ReactNode , ReactChildren , FunctionComponent , ComponentClass } from 'react' ; interface INextPage { getInitialProps ? ( ctx ) : Promise < any > ; } export interface IComponentProps { [ key ] : any ; children : ReactChildren ; } interface RenderWrapper < TProps extends IComponentProps > { ( props ) : ReactNode ; } function getComponentName ( ChildComponent ) { return ChildComponent . displayName || ChildComponent . name || 'Component' ; } function tryGetInitialPropsMethod ( child ) { const nextPage = child as INextPage ; return nextPage && nextPage . getInitialProps ; } export default function withWrapper < TPropsType extends IComponentProps > ( ChildComponent , name , render ) { const WrappedComponent = ( props ) : ReactNode => render ( props ) ; ( WrappedComponent as FunctionComponent ) . displayName = `${ name }(${ getComponentName ( ChildComponent ) })` ; const getInitialProps = tryGetInitialPropsMethod ( ChildComponent ) ; if ( getInitialProps ) { const WrappedComponentNext = WrappedComponent as INextPage ; WrappedComponentNext . getInitialProps = async ( args ) : Promise < any > => getInitialProps ( args ) ; } return WrappedComponent ; }