Zed extension that runs the TypeScript 7 native language server.
It attaches to Zed's existing JavaScript, JSX, TypeScript, and TSX languages.
TypeScript 7's language server is a native executable that ships inside the platform-specific
@typescript/typescript-<platform>-<arch> npm packages, launched in LSP mode:
tsc --lsp --stdioThe extension executes that native binary directly when it can locate it next to the resolved
typescript package (npm/bun hoisted layouts, pnpm on Linux/macOS). Otherwise it falls back to the
package's bin/tsc Node launcher — Microsoft's own resolution logic — via the worktree's node
(volta/fnm shims included) or Zed's bundled Node. No Node process stays in the middle on the native
path.
The extension resolves the TypeScript 7+ package to run, preferring the project's own copy:
tsdk.path(explicit, version checked). Accepts the package root, itslibdir (VS Codetypescript.tsdkconvention), abin/tscpath, or a platform package containing the native binary.- Any dep (dependencies/devDependencies/peerDependencies) in the worktree
package.jsonwhose effective package name istypescript: either a direct"typescript"dependency or annpm:alias under any key (such as"@typescript/native": "npm:typescript@^7"). Verifies that the installed package is >=7 and has a usable launcher. (Skips@typescript/typescript6compat aliases.) - Otherwise: managed
npm install typescriptinto the extension's own directory (version >=7 enforced).
For managed installs, version wins over updateChannel:
| Setting | Install behavior |
|---|---|
version |
Install any npm version spec, such as 7.0.2, next, or ^7.0.0. |
updateChannel: "latest" |
Install the latest stable typescript package. |
updateChannel: "next" |
Install typescript@next, matching TypeScript's nightly channel. |
TypeScript 6 and older are rejected — for those, use Zed's built-in TypeScript support instead.
All configuration lives under lsp.typescript in Zed settings. The extension owns a small set of
launch/install keys; everything else in settings is forwarded verbatim to the language server,
which pulls it via workspace/configuration.
| Setting | Meaning |
|---|---|
version |
npm version spec to install (wins over updateChannel). |
updateChannel |
"latest" or "next". |
tsdk.path |
Explicit TypeScript package location (see Server resolution). |
server.pprofDir |
Passes --pprofDir so the server writes pprof CPU/memory profiles there. |
server.goMemLimit |
Sets GOMEMLIMIT for the server. Integer bytes with optional B/KiB/MiB/GiB/TiB suffix, or off. |
server.args |
Extra CLI args appended to --lsp --stdio — forwards future server flags without an extension update. |
server.env |
Extra environment variables for the server process (e.g. GOGC, debug vars). |
Dotted ("server.pprofDir": …) and nested ("server": {"pprofDir": …}) forms are both accepted;
the nested form wins when both are set.
The current server flag surface in --lsp mode is --stdio, --pipe <name>, --socket <addr>,
and --pprofDir <dir>; anything new lands via server.args.
lsp.typescript.binary overrides how the server is launched entirely:
{
"lsp": {
"typescript": {
"binary": {
// a path ending in tsc/tsc.js/tsc.exe is launched as the server itself;
// any other path is treated as a custom node to run the resolved tsc with
"path": "/path/to/tsc",
"arguments": ["--lsp", "--stdio"], // optional: full args override
"env": { "GOMEMLIMIT": "4GiB" } // optional: highest-precedence env
}
}
}
}Environment precedence, lowest to highest: shell environment, server.env, server.goMemLimit,
binary.env.
The server requests the configuration sections js/ts, typescript, javascript, and editor,
and merges them with ascending precedence editor → javascript → typescript → js/ts. Put
those sections directly in settings — they are forwarded to the server:
{
"lsp": {
"typescript": {
"settings": {
"typescript": {
"preferences": {
"quoteStyle": "single",
"importModuleSpecifier": "non-relative",
"preferTypeOnlyAutoImports": true
}
}
}
}
}
}Matching Zed's built-in TypeScript support, the extension enables all inlay hint kinds and both code
lens kinds server-side by default (Zed's own inlay_hints setting still controls whether hints are
displayed). Your settings deep-merge over these defaults and win at leaf level, so e.g.
"typescript": {"inlayHints": {"parameterNames": {"enabled": "none"}}} turns one hint kind off
while the rest keep their defaults.
VS Code-style dotted keys are also accepted and expanded, so configuration copied from TypeScript docs works as-is (nested form wins on conflict):
{
"lsp": {
"typescript": {
"settings": {
"typescript.inlayHints.parameterNames.enabled": "all",
"js/ts.implicitProjectConfig.checkJs": true
}
}
}
}Option groups the server reads (same names as the VS Code TypeScript settings, minus the
typescript./javascript. prefix): inlayHints.*, preferences.* (quote style, auto-imports,
module specifiers, organize imports), suggest.*, format.*, referencesCodeLens.* /
implementationsCodeLens.*, validate.*, workspaceSymbols.*, autoClosingTags, and
implicitProjectConfig.* under js/ts. The authoritative list is UserPreferences in the server
source.
initialization_options are passed to the server verbatim at initialize.
Known upstream options (InitializationOptions, read in server.go):
| Option | Upstream meaning |
|---|---|
disablePushDiagnostics |
Disable automatic diagnostic pushes. |
codeLensShowLocationsCommandName |
Client command used by resolved references/implementations CodeLens. |
userPreferences |
Initial user preferences (same shape as the sections above). |
enableTelemetry |
Enable server telemetry events. |
logVerbosity |
Initial server log verbosity. |
{
"lsp": {
"typescript": {
"initialization_options": {
"enableTelemetry": false,
"logVerbosity": 2
}
}
}
}Preferences set via the configuration sections update live on workspace/didChangeConfiguration;
initialization_options only apply at server startup.
- TypeScript 7 has no stable programmatic API yet, so embedded-language workflows (Vue, MDX, Astro, Svelte, Angular templates) are not supported by the upstream server.
codeLensShowLocationsCommandNamerequires client-side command support that Zed extensions cannot register; code lenses resolve, but the "show locations" command is editor-dependent.
Prerequisite: Rust installed with rustup.
In Zed, run zed: install dev extension and select this directory.
After edits, rebuild from the Extensions page.
For logs, run Zed with zed --foreground or use zed: open log.
{ "lsp": { "typescript": { "settings": { "updateChannel": "next", "server": { "pprofDir": "./.typescript-pprof", "goMemLimit": "2048MiB", "env": { "GOGC": "50" } } } } } }