Search code examples
reactjstypescriptnpmpackagewebpack-2

error TS2339: Property 'props' does not exist on type 'TestPage'


I'm using typescript abstract class as a base class of my layout component in React, the usage of that base class looks something like this:

import { IPageLayoutActions, IPageLayoutLocalState, IPageLayoutProps, PageLayoutNoSidebar } from 'pg-face/dist/layouts/PageLayoutNoSidebar';

export interface ITestPageProps extends IPageLayoutProps
{
    loremIpsum: string;
}
export interface ITestPageActions extends IPageLayoutActions {}
interface ITestPageLocalState extends IPageLayoutLocalState {}

export
class TestPage
extends PageLayoutNoSidebar<ITestPageProps && ITestPageActions, ITestPageLocalState>
{
    renderPageContent() {
        return <span>{ this.props.loremIpsum }</span>;
    }
}

The PageLayoutNoSidebar component actually extends another class called PageLayout, which is a base class for all layouts in my application. It works when everything is inside one project.

Now I wanted to move all these layout files into separate npm module to be reusable across all my applications (I'm just testing it so I'm loading the package from local directory). So I created a package, transpiled the typecscript code into js and definition files using "tsc -d -p ./". These files are stored in the dist dir of the package. Then I updated the package in my project dir.

After that, when I try to use this class in my project, I got

error TS2339: Property 'props' does not exist on type 'TestPage'

I figured out that when PageLayoutNoSidebar doesn't extend PageLayout (I copied all the code from PageLayout directly into the PageLayoutNoSidebar), this problem disappears, so I guess there is some problem with exports.

Do you have any idea what could be wrong with the code?

This is how the code of these classes looks like:

PageLayout.tsx

import * as React from 'react';
import { Header, IHeaderActions, IHeaderProps } from '../blocks';

export interface IPageLayoutProps extends IHeaderProps {}
export interface IPageLayoutActions extends IHeaderActions {}
export interface IPageLayoutLocalState {
    headerCollapsed: boolean;
}

export
abstract class PageLayout<P extends IPageLayoutProps & IPageLayoutActions, S extends IPageLayoutLocalState>
extends React.Component<P, S>
{
    abstract render(): JSX.Element

    renderPageHeader() {
        return (
            <Header
                headerCollapsed={this.state.headerCollapsed}
                mainMenuItems={this.props.mainMenuItems}
                onHeaderToggle={this._toggleHeader}
            />
        );
    }

    renderPageContent(): JSX.Element | null {
        return null;
    }

    _toggleHeader = (headerCollapsed: boolean) => {
        this.setState({
            headerCollapsed
        });
    }

    //...
}

PageLayoutNoSidebar.tsx

import * as React from 'react';
import { IPageLayoutActions, IPageLayoutLocalState, IPageLayoutProps, PageLayout } from './PageLayout';

export
class PageLayoutNoSidebar<P extends IPageLayoutProps & IPageLayoutActions, S extends IPageLayoutLocalState>
extends PageLayout<P, S>
{
    render() {
        return (
            <div>
                {this.renderPageHeader()}
                <main className="container-narrow">
                    {this.renderPageContent()}
                </main>
            </div>
        );
    }
}

Solution

  • In the end i reworked the way how package is published. I set up the build process according to the https://dominicstpierre.com/using-typescript-to-publish-a-testable-react-npm-package-f3811b3c64e3 article.