Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TS files cannot use JSX components declared as a classes in JS/JSX file #15596

Closed
robin-anil opened this issue May 5, 2017 · 18 comments
Closed
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@robin-anil
Copy link

This is on a macbook. That is the only difference I can see

robinanil 20:19:18 :~/work/bug$ cat > tsconfig.json
{
  "compilerOptions": {
    "module": "es2015",
    "target": "esnext",
    "jsx": "react-native",
    "strictNullChecks": true,
    "allowSyntheticDefaultImports": true,
    "allowJs": true,
    "checkJs": true,
    "lib": [
      "es5",
      "es6",
      "es7",
      "es2017",
      "dom"
    ],
    "outDir": "dist"
  },
  "include": [
    "**/*.ts",
    "**/*.tsx",
    "**/*.js"
  ],
  "exclude": [
    "dist",
    "node_modules"
  ]
}
robinanil 20:19:24 :~/work/bug$ cat > index.tsx
import React from 'react';
import Hello from './hello';

class A extends React.Component<void, void> {
  render() {
    return (
      <div>
        <Hello>
          <div></div>
        </Hello>
      </div>
    );
  }
}
robinanil 20:19:36 :~/work/bug$ cat > hello.jsx
import React from 'react';

export default class Hello extends React.Component {
  render() {
    return <div>Hello</div>;
  }
}
robinanil 20:19:47 :~/work/bug$ tsc -v
Version 2.3.2
robinanil 20:19:54 :~/work/bug$ tsc -p tsconfig.json 
hello.jsx(1,19): error TS2307: Cannot find module 'react'.
index.tsx(1,19): error TS2307: Cannot find module 'react'.

Opening a new bug offshoot of #14558

@mhegazy

@robin-anil
Copy link
Author

cat package.json 
{
  "name": "bug",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "@types/react": "^15.0.24",
    "react": "^15.5.4",
    "typescript": "^2.3.2"
  }
}

@robin-anil
Copy link
Author

Ignore the output. The error is different. Let me try to repro with a copy of the real files.

@robin-anil
Copy link
Author

robin-anil commented May 5, 2017

ok. so here is the weird thing that is happening. the bug does not happen in the test directory

However in our repo, in which I replace the code such that index.tsx is pointing just to hello.jsx(with the same paths) the error happens. Now two things are different in that repo

  1. The paths are different (I have to import ../shared/components/Hello) - Doing the same on the isolated repo does not repro the issue
  2. There are other files in the repo, which tscompiler should not read because the entry point is index.tsx

Somehow (2) might be trickling a bug with the compiler but isolated two class tests are not able to repro this... That is the insight I have so far.

@mhegazy
Copy link
Contributor

mhegazy commented May 5, 2017

@r-tock i will need a self contained repro to be able to debug more and identify the issue. can you share more context for this issue.

@mhegazy mhegazy added the Needs More Info The issue still hasn't been fully clarified label May 5, 2017
@robin-anil
Copy link
Author

I know...I am trying my best to isolate. The only difference between the self-contained version and my version is the other files in the repo, which should not be read or resolved by the compiler. I am slowly deleting a file one by one to see what is causing the issue

@mhegazy
Copy link
Contributor

mhegazy commented May 5, 2017

thanks!

@robin-anil
Copy link
Author

robin-anil commented May 7, 2017

Ok I now have a repro. This has to do with the way we were referencing files outside the folder and that works for our babel based jsx code, typescript resolver maybe doing something weird here.

robinanil 14:55:37 :~/work/bug$ ls
main   shared
robinanil 14:55:46 :~/work/bug$ ls -lh main/
total 40
drwxr-xr-x   4 robinanil  staff   136B May  7 14:51 dist
drwxr-xr-x  28 robinanil  staff   952B May  7 14:50 node_modules
-rw-r--r--   1 robinanil  staff   618B May  4 22:07 package.json
lrwxr-xr-x   1 robinanil  staff    10B May  7 14:55 shared -> ../shared/
drwxr-xr-x   3 robinanil  staff   102B May  7 14:53 src
-rw-r--r--   1 robinanil  staff   573B May  7 14:55 tsconfig.json
-rw-r--r--   1 robinanil  staff   6.7K May  7 14:50 yarn.lock
robinanil 14:55:54 :~/work/bug$ tree main/src/
main/src/
└── js
    └── index.tsx

1 directory, 1 file
robinanil 14:56:01 :~/work/bug$ tree shared/
shared/
└── src
    └── js
        ├── BaseComponent.jsx
        └── hello.jsx

2 directories, 2 files
robinanil 14:56:04 :~/work/bug$ cat main/src/js/index.tsx 
import * as React from 'react';
import Hello from 'shared/hello';

class A extends React.Component<any, any> {
  render() {
    return (
      <div>
        <Hello skip={true} />
      </div>
    );
  }
}
robinanil 14:56:11 :~/work/bug$ cat shared/src/js/
BaseComponent.jsx  hello.jsx          
robinanil 14:56:11 :~/work/bug$ cat shared/src/js/BaseComponent.jsx 
import React from 'react';

/**
 * The base component that autobinds all the methods to this.
 */
class BaseComponent extends React.Component {
  constructor(props) {
    super(props);
    Object.getOwnPropertyNames(Object.getPrototypeOf(this)).forEach((method) => {
      if (typeof this[method] !== 'function') {
        return;
      }
      this[method] = this[method].bind(this);
    });
  }
}

export default BaseComponent;
robinanil 14:56:19 :~/work/bug$ cat shared/src/js/hello.jsx 
import React from 'react';

import BaseComponent from './BaseComponent'

class Hello extends BaseComponent {
  render() {
    if (this.props.skip) {
      return null;
    }
    return <div>Hello</div>;
  }
}

export default Hello;
robinanil 14:56:22 :~/work/bug$ cat main/tsconfig.json 
{
  "compilerOptions": {
    "module": "es2015",
    "target": "esnext",
    "jsx": "react-native",
    "strictNullChecks": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "node",
    "allowJs": true,
    "checkJs": true,
    "outDir": "dist",
    "lib": [
      "es5",
      "es6",
      "es7",
      "es2017",
      "dom"
    ],
    "baseUrl": ".",
    "rootDir":  "..",
    "paths": {
      "shared/*": ["../shared/src/js/*"]
    }
  },
  "exclude": [
    "dist"
  ],
  "files": [
    "src/js/index.tsx"
  ]
}
$ tsc -p tsconfig.json 
src/js/index.tsx(8,9): error TS2605: JSX element type 'Hello' is not a constructor function for JSX elements.
  Property 'setState' is missing in type 'Hello'.
src/js/index.tsx(8,9): error TS2607: JSX element class does not support attributes because it does not have a 'props' property.
../shared/src/js/BaseComponent.jsx(1,19): error TS2307: Cannot find module 'react'.
../shared/src/js/hello.jsx(1,19): error TS2307: Cannot find module 'react'.
../shared/src/js/hello.jsx(7,14): error TS2339: Property 'props' does not exist on type 'Hello'.

If I change the path to use shared directory symlink

$ ln -s ../shared shared
- "shared/*": ["../shared/src/js/*"]
+ "shared/*": ["./shared/src/js/*"]
$ tsc -p tsconfig.json 
$ echo $?
0

@RyanCavanaugh RyanCavanaugh removed the Needs More Info The issue still hasn't been fully clarified label May 8, 2017
@mhegazy
Copy link
Contributor

mhegazy commented May 8, 2017

Still no luck reproducing this... what is your OS?

@robin-anil
Copy link
Author

MacOS Sierra 10.12.14. Using nvm (for node installation)

@mhegazy
Copy link
Contributor

mhegazy commented May 8, 2017

i will need to find a mac to test this on..

@robin-anil
Copy link
Author

I am on Node 7.9

@yuit
Copy link
Contributor

yuit commented May 8, 2017

@mhegazy .... I can take a look at this on my mac

@mhegazy
Copy link
Contributor

mhegazy commented May 8, 2017

thanks!
here is my sample based on @r-tock's description above:

15596.zip

@robin-anil
Copy link
Author

robin-anil commented May 8, 2017

@mhegazy @yuit I can verify that I can repro it from the archive you just uploaded by changing shared/* to ../shared/* in tsconfig.json

@mhegazy
Copy link
Contributor

mhegazy commented May 8, 2017

I see. thanks. this makes sense. when resolving the module import to the outer file, its import to react can not be resolved any more, since react is main\node_modules\@types\react and not one level higher.

using ../shared is not correct if you already have a symlink for shared locally. if you want to do that, make sure you add an entry to map react to your local node_modules as well.

@mhegazy mhegazy added the Working as Intended The behavior described is the intended behavior; this is not a bug label May 8, 2017
@robin-anil
Copy link
Author

using symlink for shared is actually a work around...

We use a mono repo and does not follow the npm+git packaging model. For us, various app directories are siblings of shared or libraries. So we cannot afford to symlink all the time this was just an illustration, I am at the moment converting our large codebase to typescript.

How can I make the resolver look in main\node_modules for types?

@mhegazy
Copy link
Contributor

mhegazy commented May 8, 2017

depending on what you are looking for, for react for instance, add node_modules\@types to your paths, if the package has its own types, then add node_modules, so:

    "paths": {
      "shared/*": ["../shared/src/js/*"],
      "*": ["node_modules/*", "node_modules/@types/*"]
    }

should do the trick.

@robin-anil
Copy link
Author

Thanks this helps a lot. Closing the issue

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants