A tiny VS Code extension with one command:
DTS View: Open Beside — generates the .d.ts declaration for the active .ts/.tsx
file and shows it in a single, persistent read-only panel beside the source — like Markdown's
"Open Preview to the Side". The panel follows the active editor and live-updates as you type,
so there's only ever one preview tab. Nothing is written to disk.
foo.ts foo.d.ts (virtual, read-only)
------------------------ ------------------------------
import type { Foo } from import type { Foo } from "./types";
"./types"; export declare function makeFoo(): Foo;
export function makeFoo() export interface Bar {
: Foo { ... } foo: Foo;
export interface Bar { }
foo: Foo;
}
Open the Extensions view and search DTS View — VS Code pulls from the Marketplace; Cursor, VSCodium, and Gitpod pull from Open VSX. Or from the command line:
code --install-extension appfigures.dts-view # VS Code
cursor --install-extension appfigures.dts-view # Cursor
codium --install-extension appfigures.dts-view # VSCodiumThen open a .ts/.tsx file and run DTS View: Open Beside (Cmd/Ctrl+Shift+P). Updates arrive
automatically through the marketplace, like any other extension.
- Registers a
TextDocumentContentProviderunder the customdts-view:URI scheme; the tab is read-only because virtual documents have no on-disk backing. - Walks upward from the active file to the nearest
tsconfig.jsonand parses it with TypeScript's own config APIs, soextends, path mappings,jsx, and module resolution all apply. Falls back to sensible defaults when there's no config. - Builds a real TypeScript
Programrooted at the project's files (nottranspileDeclaration), so inferred exported types can draw on project-wide type information across files. - Uses a custom
CompilerHostthat serves the editor's current, unsaved buffer for the active file while resolving the rest of the project from disk. Declaration output is captured in memory by interceptingwriteFile. - One persistent panel. The preview lives at a single fixed
dts-view:URI, so there's only ever one tab; running the command again, switching files, or typing all update it in place. (A text-editor tab can't be renamed per file — no title API — so a one-line header comment names the file the panel is currently showing.) - Follows the active editor + live-updates (debounced ~300ms; no save needed). Updates are scoped to the mirrored file's own edits and to editor switches; editing a different imported file won't refresh it. Each refresh rebuilds a full Program, so on a very large project a rebuild can lag a beat behind your typing/switching.
typescriptis pinned to^5.9.3on purpose.typescript@7.xis the new native (Go) port: its main entrypoint exports only a version string and the programmatic compiler API is exposed only under an explicitly-unstabletypescript/unstable/*surface. The classic API this extension relies on —createProgram, a customCompilerHost,parseJsonConfigFileContent, per-fileprogram.emit— does not exist at the main entrypoint in 7.x. 5.9.x is the latest line that ships it. Revisit when the native port stabilizes that API.
npm install
npm run compile # tsc -> out/extension.js (npm run watch to rebuild on change)
code . # then press F5 to launch the Extension Development HostIn the [Extension Development Host] window, open any .ts/.tsx file and run
DTS View: Open Beside. Type to watch it update, or switch files and the panel follows.
npm run package builds a self-contained .vsix (it bundles the typescript package it needs at
runtime, including the lib.*.d.ts files the compiler reads for global types).
Releases are automated: pushing a v* tag runs .github/workflows/publish.yml, which builds
the .vsix and publishes the same artifact to the VS Code Marketplace and Open VSX, then attaches
it to a GitHub Release.
# bump "version" in package.json first, then:
git tag v0.0.1 && git push origin v0.0.1One-time setup:
- Icon — export
icon.svgto a 128×128icon.pngand add"icon": "icon.png"topackage.json(Marketplace listings look unfinished without one), e.g.npx svgexport icon.svg icon.png 128:128. - Marketplace token — create a publisher named
appfigures(Azure DevOps), generate a PAT scoped to Marketplace → Manage, and add it as the repo secretVSCE_PAT.⚠️ Global Azure DevOps PATs retire 2026-12-01 — after that, switch CI to Microsoft Entra ID auth. - Open VSX token — sign the Eclipse Publisher Agreement at open-vsx.org, create the
appfiguresnamespace (npx ovsx create-namespace appfigures -p <token>), and add the token asOVSX_PAT.
To publish by hand instead of via CI: npx vsce publish -p <VSCE_PAT> and
npx ovsx publish dts-view-<version>.vsix -p <OVSX_PAT>.
Intentionally small: no source-map/navigation back to source, no settings, no sidebar, no temp files. Single persistent panel, follow-the-editor, and live update while typing are all in — see "How it works".