volar-service-typescript@0.0.71 and volar-service-typescript-twoslash-queries@0.0.71 import typescript from their type declarations, but neither manifest declares typescript in dependencies or peerDependencies.
| package |
.d.ts files importing typescript |
example |
volar-service-typescript |
14 |
index.d.ts:4 — export declare function create(ts: typeof import('typescript'), …) |
volar-service-typescript-twoslash-queries |
1 |
index.d.ts:2 — export declare function create(ts: typeof import('typescript')): LanguageServicePlugin |
Why it matters
With a hoisting installer (npm / Yarn classic) this resolves by accident, because typescript gets flattened into the top-level node_modules. With an isolated layout it only resolves when the package's real path happens to sit under a node_modules that has typescript as an ancestor. Two setups where that ancestor walk fails, both verified:
- A store outside the project — pnpm's global virtual store, and any comparable content-addressed layout.
- Hoisting disabled (
hoist=false / hoistPattern: []), even with the ordinary project-local store.
In those cases tsc reports Cannot find module 'typescript' or its corresponding type declarations inside the published .d.ts, every ts.* type silently degrades to any, and downstream module augmentation stops applying — so consumers see errors that look unrelated to a missing dependency.
Suggested fix
An optional peer dependency keeps the runtime contract intact — both packages receive the ts instance from their caller and never require('typescript') themselves — while making the types resolvable:
{
"peerDependencies": {
"typescript": "*"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
}
Optional matters here: a required peer would make installers pull typescript into projects that only consume the runtime.
The same problem affects @volar/typescript, @volar/language-server and @volar/language-service in volarjs/volar.js; it is tracked there as volarjs/volar.js#284.
Happy to send a PR for both packages if that direction looks right to you.
Written by an agent (Claude Code, claude-opus-5), on behalf of the pnpm maintainers — this surfaced while triaging pnpm/pnpm#13331.
volar-service-typescript@0.0.71andvolar-service-typescript-twoslash-queries@0.0.71importtypescriptfrom their type declarations, but neither manifest declarestypescriptindependenciesorpeerDependencies..d.tsfiles importingtypescriptvolar-service-typescriptindex.d.ts:4—export declare function create(ts: typeof import('typescript'), …)volar-service-typescript-twoslash-queriesindex.d.ts:2—export declare function create(ts: typeof import('typescript')): LanguageServicePluginWhy it matters
With a hoisting installer (npm / Yarn classic) this resolves by accident, because
typescriptgets flattened into the top-levelnode_modules. With an isolated layout it only resolves when the package's real path happens to sit under anode_modulesthat hastypescriptas an ancestor. Two setups where that ancestor walk fails, both verified:hoist=false/hoistPattern: []), even with the ordinary project-local store.In those cases
tscreportsCannot find module 'typescript' or its corresponding type declarationsinside the published.d.ts, everyts.*type silently degrades toany, and downstream module augmentation stops applying — so consumers see errors that look unrelated to a missing dependency.Suggested fix
An optional peer dependency keeps the runtime contract intact — both packages receive the
tsinstance from their caller and neverrequire('typescript')themselves — while making the types resolvable:{ "peerDependencies": { "typescript": "*" }, "peerDependenciesMeta": { "typescript": { "optional": true } } }Optional matters here: a required peer would make installers pull
typescriptinto projects that only consume the runtime.The same problem affects
@volar/typescript,@volar/language-serverand@volar/language-serviceinvolarjs/volar.js; it is tracked there as volarjs/volar.js#284.Happy to send a PR for both packages if that direction looks right to you.
Written by an agent (Claude Code, claude-opus-5), on behalf of the pnpm maintainers — this surfaced while triaging pnpm/pnpm#13331.