Repository navigation
[typings-generator] Support declaration source maps so "go to definition" resolves to the source file #5906
Description
Summary
Typings generated by @rushstack/typings-generator (and its consumers, such as
@rushstack/heft-localization-typings-plugin and @rushstack/heft-sass-plugin) are emitted into a
separate folder that is merged back into the source tree via the TypeScript rootDirs compiler
option. A typical rig configures something like:
"rootDirs": ["../src", "../temp/loc-ts", "../temp/sass-ts"]This means the TypeScript language service only ever sees the generated .d.ts. The file that
actually declares the string — the .resx, or the .scss — is invisible to it.
The practical effect is that "go to definition" (alt-click / cmd-click) on a localized string, or on
its import specifier, navigates the developer to the generated declaration file rather than to the
file they can actually edit:
import strings from '../loc/Strings.resx';
strings.AddComment; // -> temp/loc-ts/loc/Strings.resx.d.ts, not src/loc/Strings.resxSince the generated declaration is a build artifact, landing there is a dead end: the developer has
to close it and locate the real source by hand. For a large repo this is a constant, repeated
friction, and it applies to every project that consumes generated typings.
Repro steps
- Configure a project that uses
heft-localization-typings-pluginto generate typings for a
.resxfile into a folder listed inrootDirs. - In a
.tsfile, import the.resxand reference one of its strings. - Alt-click (or F12) the string property, or the import specifier.
Expected result: the editor opens the .resx file, ideally on the <data name="..."> element
that declares that string.
Actual result: the editor opens the generated .resx.d.ts under the generated typings folder.
Details
TypeScript already has a general mechanism for exactly this: declaration source maps
(.d.ts.map). When a .d.ts has an adjacent .d.ts.map pointing back at a real source file,
tsserver transparently redirects "go to definition" to that source. This is the same machinery that
makes project-references navigation work.
Nothing in the generated-typings path emits such a map today, so tsserver has nothing to redirect
with.
This seems well suited to being solved inside typings-generator rather than by each consumer,
because the generator composes the output line by line and therefore already knows the exact
position of every declaration it emits. A consumer trying to solve it downstream would have to
re-parse the generator's output with a regex and would break whenever the emit format changed.
Sketch of an approach:
typings-generatorgains an opt-ingenerateDeclarationMapsoption and emits a.d.ts.map
beside each generated.d.ts.- Parsers may optionally report the source position of each declaration. Parsers that do not are
unaffected, and no map is emitted when positions are unavailable. - The map is serialized per output folder, so the relative path back to the source stays correct for
secondary output folders as well. - Consumers such as
heft-localization-typings-pluginexpose the option through their config
schema, defaulting to off.
Because both localization typings and Sass typings route through the same generator, a fix at that
layer covers both.
I have a working implementation of this and would like to contribute it as a PR.
Standard questions
| Question | Answer |
|---|---|
| Package name: | @rushstack/typings-generator |
| Package version? | 0.16.22 |
| Operating system? | Mac (also reproduced on Linux) |
| Would you consider contributing a PR? | Yes |
Node.js version (node -v)? |
22.21.1 |
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsClosed
Activity