node.jsvisual-studio-codeintellisensecommonjsgo-to-definition

How can I use "Go To Definition" for CommonJS `require`s in VS Code when the path to resolve is derived using runtime functions and values?


I want to be able to use Go to definition feature in VS Code for path such as:

const path = require('path');
const mypath = require(path.resolve('my', 'path'));

How can I configure in a way for VS Code to recognize those paths?

Here is an example of what I'm talking about:

enter image description here

I want to be able to use the "Go To Definition" action on my mypath variable in the above example code.


Solution

  • VS Code and TypeScript don't try that hard to figure out whether something returned from the output of a runtime function like path.resolve is knowable at statically / at "compile"-time. Just switch to using require("my/path") instead of require(path.resolve("my", "path")). I don't see a reason to do it that way anyway-- If you thought you needed to handle different path separator characters for Windows when using require, you don't need to because NodeJS' require resolves POSIX-style paths in an OS-independent fashion (POSIX paths in the path argument to require will work on NodeJS on Windows). Straight from the docs:

    The relative paths of POSIX style are resolved in an OS independent fashion, meaning that the examples above will work on Windows in the same way they would on Unix systems.

    If you're actually using path.resolve with more complicated inputs that are derived at runtime and are impossible to derive statically, then it would be impossible by definition for IntelliSense to provide you such a facility, since IntelliSense generally works based on static analysis.

    If it is statically derivable, and you want to get such a feature, it's not a matter of configuring something in VS Code to get it to happen. It's a matter of whether tsserver supports it at all. If it doesn't (which is the case currently with the example you have provided), the only way you'll get it is by first asking for such functionality by raising a feature-request issue ticket to the TypeScript maintainers.

    Though for practical purposes, forgetting the Go To Definition problem for now and thinking about type information, you might be able to work around this if both import file routes have the same exported interface, by just using JSDoc annotations to say that the type of the result of the dynamic import. Ex.

    function getModulePath() { return condition ? "foo" : "bar" }
    /**@type {typeof await import("foo")}*/
    const module = await import(getModulePath());
    

    Something along those lines. I haven't checked.