As other answers have already stated,
You can use the TypeScript: Go to Source Definition
command to go to the symbol definition in the JS file (Regardless of any of your tsconfig and whether the package you are requiring/importing things from provides type declaration files, or whether you installed a Definitely Typed package for it or not). This functionality is provided TypeScript and the vscode.typescript-language-features
extension (which is built-into / ships out-of-box with VS Code).
VS Code Nightly also currently includes a new setting: "JavaScript: Prefer Go To Source Definition" and corresponding "TypeScript: Prefer Go To Source Definition", which makes "Go To Definition" first attempt going to the Source Definition, and fallback to the typings definition if a source definition cannot be found. (source).
I thought I'd try to give more interesting information that other answers haven't covered yet for fun and profit curiosity's sake (and also explain why this "often" happens to you, but not always):
You can bind that command to a keybinding. It's keybinding command ID is typescript.goToSourceDefinition
.
If the package you require
or import
packages its own type declaration files or you installed a community-maintained type declaration file from the Definitely Typed project, then ctrl+clicking / cmd+clicking into the require
/import
argument or putting the caret on it and invoking whatever the editor.action.revealDefinition
command or editor.action.goToTypeDefinition
are bound to (F12 by default for editor.action.revealDefinition
) will take you to the type declaration by default.
If the package you require
or import
doesn't package its own type declarations and you didn't install a types package from the Definitely Typed project, and you modify your tsconfig or jsconfig to set allowJs: true
and maxNodeModuleJsDepth: <N>
, then ctrl+clicking / cmd+clicking into the require
/import
argument or putting the caret on it and invoking whatever the editor.action.revealDefinition
command or editor.action.goToTypeDefinition
command are bound to (F12 by default for editor.action.revealDefinition
) will take you to the symbol's definition in the JS file by default (unless you already performed this action at a point when a type declaration file declaration types for symbol was available and have not since reloaded/restarted VS Code or edited your tsconfig/jsconfig file, because it will cache that association in memory (smells like minor bug, but ¯\_( ツ )_/¯)).
The editor.action.revealDeclaration
keybinding seems to do nothing here (at the time of this writing). I guess that keybinding is more for languages like C and C++.
Some loosely related release notes sections and user docs (non-exhaustive list (I don't get paid to do this)):
Quoting from that last one:
One of VS Code's longest standing and most upvoted feature requests is to make VS Code navigate to the JavaScript implementation of functions and symbols from external libraries. Currently, Go to Definition jumps to the type definition file (the .d.ts
file) that defines the types for the target function or symbol. This is useful if you need to inspect the types or the documentation for these symbols but hides the actual implementation of the code. The current behavior also confuses many JavaScript users who may not understand the TypeScript type from the .d.ts
.
While changing Go to Definition to navigate to the JavaScript implementation of a symbol may sound simple, there's a reason why this feature request has been open for so long. JavaScript (and especially the compiled JavaScript shipped by many libraries) is much more difficult to analyze than a .d.ts.
Trying to analyze all the JavaScript code under node_modules would be both slow and would also dramatically increase memory usage. There are also many JavaScript patterns that the VS Code IntelliSense engine is not able to understand.
That's where the new Go to Source Definition command comes in. When you run this command from either the editor context menu or from the Command Palette, TypeScript will attempt to track down the JavaScript implementation of the symbol and navigate to it. This may take a few seconds and we may not always get the correct result, but it should be useful in many cases.
See also: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#go-to-source-definition.