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

Recursively Resolving Modules #10649

Open
bezreyhan opened this issue Aug 31, 2016 · 15 comments
Open

Recursively Resolving Modules #10649

bezreyhan opened this issue Aug 31, 2016 · 15 comments
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript

Comments

@bezreyhan
Copy link

TypeScript Version: 2.1.0

I'm using ts-loader and Webpack to compile my .ts files. In My Webpack config I have the following configuration:

resolve: {
  modulesDirectories: ['shared', 'node_modules']
}

This allows me to import a component that lives in the shared directory without spelling out the full relative path. Example:
import Button from 'components/Button'

Webpack will walk up the directory tree and use the first shared directory it finds (the same way it does with the node_modules directories). This way, the component can live in the ../../shared/components/Buttton.tsx and Webpack will find it and bundle it.

My files compile fine because I am using ts-loader but I am getting can not find module errors in my editor.

Is there a way to tell the TS compiler to recursively look for the component in the shared directories?

I noticed the new baseUrl and paths configuration option but to my knowledge you can not use paths to recursively look for a directory.

@mhegazy
Copy link
Contributor

mhegazy commented Aug 31, 2016

I noticed the new baseUrl and paths configuration option but to my knowledge you can not use paths to recursively look for a directory.

well not fully. but it can emulate the behavior, e.g.

"paths" : {
    "*": [
             "./node_modules/*",
             "../node_modules/*", 
             "../../node_modules/*", 
             "../../../node_modules/*" 

              // you get the idea..
          ] 
}

@bezreyhan
Copy link
Author

bezreyhan commented Sep 1, 2016

@mhegazy

I just added this to my tsconfig:

"paths": {
    "*": [
      "./shared/*",
      "../shared/*",
      "../../shared/*",
      "../../../shared/*",
      "../../../../shared/*",
      "../../../../../shared/*",
      "../../../../../../shared/*"
    ]
  },

but I'm still getting the errors.

I ran tsc with traceResolution and grep'd for shared but nothing came up. It doesn't seem like tsc is looking in the shared folders for the modules.

@mhegazy
Copy link
Contributor

mhegazy commented Sep 1, 2016

Can u share a repro.

@bezreyhan
Copy link
Author

@mhegazy Here is a repro: https://github.com/bezreyhan/ts-paths

After you npm install, you can run node_modules/.bin/tsc and see that the helper function in the shared folder can not be found.

Also the output of node_modules/.bin/tsc --traceResolution | grep shared is empty.

@mhegazy
Copy link
Contributor

mhegazy commented Sep 1, 2016

A few of issues here.

  • "paths" is a compiler option, so it should be under the "compilerOptions" node. otherwise it is ignored.
  • the paths on the right hand-side of the paths map are all relative to "baseUrl", so you need to specify one
  • you do not need the recursive look ups in this case since you have only one "shared" folder, the recursive lockups would be needed if you had multiple "shared" folders each on a different level, and you wanted the compiler to try them all.

here is a working tsonfig for you:

{
  "compilerOptions": {
    "sourceMap": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "module": "commonjs",
    "target": "es6",
    "jsx": "react",
     "baseUrl": "./",
     "paths": {
        "*": [
          "src/shared/*"
        ]
    }
  },
  "include": [
    "./src/first/second/third/page.ts"
  ]
}

@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Sep 1, 2016
@bezreyhan
Copy link
Author

bezreyhan commented Sep 1, 2016

@mhegazy Not putting paths within compilerOptions was a silly oversight by me. Thanks for pointing me the right way.

However, I still need recursive lookups (In the repro I wanted to keep it simple so I only put one shared folder). If my baseUrl is set to './' the resolution will begin at the root of the project. I wanted the resolution to begin at the file that is importing a module and then recursively move up the directory tree.

Can you give me any pointers here?

@mhegazy
Copy link
Contributor

mhegazy commented Sep 1, 2016

i miss understood then. I do not think there is an easy way to do this.

@bezreyhan
Copy link
Author

Hmm, would this be something the TS team would consider implementing? Being able to designate another directory name other than node_modules would be a useful.

For example, many people in the React community use Webpack's modulesDirectories config option to implement this sort of folder structure: https://gist.github.com/ryanflorence/daafb1e3cb8ad740b346

@mhegazy
Copy link
Contributor

mhegazy commented Sep 2, 2016

would it be possible to have the same compoenent "overridden" in multiple "shared" folder, e.g.:

app
├── screens
│   ├── Admin
│   │   ├── shared
│   │   │       ├── Module.js
│   │   └── index.js   // imports ./shared/Module
├── shared
│   └── Module.js
└── index.js // imports ./shared/Module and not ./screens/Admin/Shared/Module

@bezreyhan
Copy link
Author

Sorry for the delayed response.

Yes it would. It function the same way that Node looks for the node_modules.

Here is the Webpack documentation: https://webpack.github.io/docs/configuration.html#resolve-modulesdirectories

@mhegazy mhegazy added Suggestion An idea for TypeScript Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. and removed Question An issue which isn't directly actionable in code labels Sep 12, 2016
@mhegazy
Copy link
Contributor

mhegazy commented Sep 12, 2016

We do something similar to this in classic module resolution that walks up the folder structure to find a match. we will need a proposal on how to update the resolution to enable this.

@wclr
Copy link

wclr commented Sep 21, 2016

It would be very useful if TS supported more advanced ala webpack resolution strategies. https://webpack.github.io/docs/configuration.html#resolve-alias

but no need be as much sophisticated it believe

@Ciantic
Copy link

Ciantic commented Sep 24, 2016

Edit2 I can't get the webpack to work with my below trick, it works for some files.

Btw, for now it's easiest to just drop a symbolic link "Components" to the node_modules. It works even on Windows. Then one can simply do import { Blaa } from "Components/Blaa";And create a simple NPM post install script that uses node's fs.symlink and it should make it pretty good.

@kamranayub
Copy link

I know this was made in 2016 but I was going to use this approach on a new project and ran into this issue. I don't know much about TSC internals but I might spend some time to see what this might entail.

I would be apt to propose a similar compiler option as rootDirs but just moduleDirs that the Node resolution strategy would use when it walks up the directory tree. Similar to other tools, by default the value of moduleDirs is just ["node_modules"] but when overridden you can provide other directories, e.g. ["node_modules", "shared"]. I think the same resolution strategy logic should work, it just will change from only considering node_modules to considering all entries in the moduleDirs option.

@jquense
Copy link

jquense commented Jan 7, 2019

this is a huge blocker to adopting typescript on larger projects. I've been trying to come up with a flow to typescript migration for a lot of our projects and without this option it's just infeasible.

We need an option that allows customizing which modules are node_modules

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants