1

I have a NPM module developed in typescript. This module is a simple, proof-of-concept react component:

import * as React from "react";
import * as ReactDOM from "react-dom";

export class COne extends React.Component<{}, {counter : number}> {
    constructor(props: {}, context: any) {
        super(props, context);
    }

    render() {
        return <h1 ref="h1">Test from comp one</h1>;
    }
}

By using tsc and appropriate tsconfig.json, I generate js files.

In another project, I import this npm module and I can render the component COne without issue.

In the second project, I then created another component, CTwo, which extends COne:

import * as React from "react";
import { COne }  from "repo1";

export class CTwo extends COne {
    constructor(props: {}, context: any) {
        super(props, context);
    }
}

If I run tsc --jsx react src/app.tsx, where app.tsx imports and renders component CTwo, all is fine. But if I run tsc --jsx react src/app.tsx typings/index.d.ts where my typings file includes react and react-dom definitions (see below), I get this error

src/app.tsx(8,21): error TS2605: JSX element type 'CTwo' is not a constructor function for JSX elements.
  Property 'render' is missing in type 'CTwo'.

My typings.json file contains current react definition and react-dom definition (I'm using the current typed-react because the official one is missing typings for JSX and it has problems when compiling with noImplicitAny):

{
  "name": "repo2",
  "dependencies": {
    "react": "github:cantide5ga/typed-react",
    "react-dom": "registry:npm/react-dom#15.0.1+20160826174104"
  }
}

I also installed ts-node and within a REPL, I imported COne from "repo1" and CTwo. I see that CTwo does not have a render method on the prototype (it does not have __proto__ property).

Even though I get the error, it works in the browser, when processed with webpack. Note, that even if I add a render method, I get another error, that Property 'setState' is missing in type 'CTwo'..

Here is the output from ts-node:

$ ts-node
> import { CTwo } from "./src/CTwo";
'use strict'
> import { COne } from "repo1";
undefined
> let x = new CTwo({}, {});
undefined
> let y = new COne({}, {});
undefined
> x.__proto__
⨯ Unable to compile TypeScript
[eval].ts (1,3): Property '__proto__' does not exist on type 'CTwo'. (2339)
> y.__proto__
COne { constructor: [Function: COne], render: [Function] }

So it seems that CTwo object is not properly extended. Should I be using a different syntax for extending react components?

I am using typescript 2.1.4. The generated CTwo.js "looks right", despite the errors emitted:

"use strict";
var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var repo1_1 = require("repo1");
var CTwo = (function (_super) {
    __extends(CTwo, _super);
    function CTwo(props, context) {
        return _super.call(this, props, context) || this;
    }
    return CTwo;
}(repo1_1.COne));
exports.CTwo = CTwo;
miha
  • 3,287
  • 3
  • 29
  • 44
  • `__proto__` is not an ES5 standard, so TypeScript doesn't output it, if you're not targeting ES6. https://github.com/Microsoft/TypeScript/issues/1601 – Radio- Dec 21 '16 at 18:18
  • In any case, this is how I extend React components, and I haven't run into this. However I'm on a different version of TypeScript with different React typings - one or the other might be the culprit. – Radio- Dec 21 '16 at 18:24
  • @Radio-, so you're saying you're doing the same thing and it works for you? Which versions and typings are you using? – miha Dec 21 '16 at 19:35
  • Typescript: 1.8, react typings: definitelyTypes 0.14.4 – Radio- Dec 21 '16 at 21:00

1 Answers1

0

After digging some more, I found out that repo1 definitions were not found by typescript, although they were not initially reported. The issue was in repo1's package.json file, and I got a hint from here: Could not find a declaration file for module 'module-name'. '/path/to/module-name.js' implicitly has an 'any' type

The point is, the main: js/index.js had to be changed to main: js/index (without suffix) and then repo2 could properly resolve repo1 and there would be no issues whatsoever.

As @Radio- mentions, extending like this works without problems, once TS is able to get hold of relevant delarations.

Community
  • 1
  • 1
miha
  • 3,287
  • 3
  • 29
  • 44