coc-tsserver: VS Code's TypeScript language features inside Neovim
Tsserver extension for coc.nvim that provide rich features like VSCode for javascript & typescript
At a glance
- What is it?
- coc-tsserver is a coc.nvim extension that drives Microsoft's tsserver language service, so Neovim users get completion, go to definition, refactoring and inlay hints from the same engine VS Code uses. It suits a Vim or Neovim developer who refuses to leave the editor for JavaScript and TypeScript, and the TypeScript version it uses is a configuration decision rather than a fixed one.
- Who is it for?
- coc-tsserver fits a Vim or Neovim developer working on a TypeScript codebase who wants editor parity with VS Code without switching, because the extension is a fork of the extension VS Code bundles, so the feature set tracks the real one.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 20 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A fork of the extension VS Code already ships
coc-tsserver is a tsserver language server extension for coc.nvim, and it exists because tsserver is part of TypeScript and provides rich language features for javascript and typescript.
The important provenance is stated in the documentation: this extension is a fork of the `typescript-language-features` extension which is bundled with VSCode.
That single fact explains most of what the project does and how it evolves. Rather than reimplementing a language service in Vim script or Lua, the extension takes the code Microsoft ships with its own editor and adapts it to coc.nvim's extension API. The feature list says it plainly: almost the same as VSCode.
The features cover the full language service surface. Code completion. Go to definition, with a link to the upstream issue explaining the mechanism. Code validation and document highlight. Document symbols of the current buffer, and folding and folding range of the current buffer. Format current buffer, range format and format on type. Hover for documentation. Implementations and references codeLens. Organize imports. Quickfix using code actions, and code refactor using code actions.
The source code actions are a list in their own right: fix all fixable JS and TS issues, remove all unused code, add all missing imports, organize imports, sort imports, and remove unused imports. Then find references, signature help, call hierarchy, selection range, semantic tokens, and rename symbols support.
Two of these are worth calling out because they are not things most LSP servers do well. Call hierarchy requires the language server to compute the callers of a function and the callees of a function, which is a genuinely hard analysis. Selection range is the inverse of expand selection, and it requires the server to know the semantic nesting at a cursor. Both come free with tsserver and would be substantial work in a from-scratch server.
One thing the extension explicitly does not do is file type detect and syntax highlight. Those are not supported by this extension, and the documentation says to use other vim plugin instead, which is a sensible division of labour since highlighting is a filetype and treesitter matter rather than a language service matter.
The licence is MIT, the last push was on 2026-10-03, and there are no GitHub releases, with the package version at 2.4.1.
Which TypeScript version runs, and the rule that changed in v2.0.0
The most consequential configuration in this extension is which copy of TypeScript the language server uses, because the version determines the available language features.
The rule as of v2.0.0 is stated in an important note. From v2.0.0, the tsserver module is resolved first from the global configuration `tsserver.tsdk` and the bundled module is used when not found. If `tsserver.useLocalTsdk` is enabled, the workspace folder configured `tsserver.tsdk` or the typescript module inside the current workspace folder would be used when it exists.
The practical consequence is that a project pinned to TypeScript 4.9 will get the 4.9 language service if the module is resolvable from the workspace, and a project on TypeScript 5.8 will get 5.8, which means the diagnostics and the suggestions match what the project's own compiler will accept. Getting that wrong produces the classic complaint of a language server suggesting syntax the project's `tsconfig` forbids.
There are three settings that shape the resolution, and they interact in a way worth reading carefully.
`tsserver.tsdk` specifies the folder path to the tsserver and the `lib*.d.ts` files under a TypeScript install to use for IntelliSense, for example `./node_modules/typescript/lib`. When specified as a user setting, the TypeScript version from `tsserver.tsdk` automatically replaces the built-in TypeScript version. When specified as a workspace setting, the tsserver is used when `tsserver.useLocalTsdk` is true.
`tsserver.useLocalTsdk` uses tsserver from the typescript module in the workspace folder and ignores the `tsserver.tsdk` configuration. Default: `false`.
And the command `:CocCommand tsserver.chooseVersion` chooses a different typescript version for the current project, which is the escape hatch when the settings do not do what you expected.
So there is a user setting, a workspace setting, and a local module, and the precedence between them is what the `tsserver.chooseVersion` command exists to resolve. That is a slightly fiddly design, and it is fiddly for a good reason: it has to accommodate the Yarn 2 PnP case, where there is no `node_modules` directory at all.
Installing it, and the Yarn 2 case
Installation is a single command inside the editor:
:CocInstall coc-tsserverThat is the whole path for most users, and it is worth noting what is not required. There is no need to install TypeScript yourself, because the extension bundles a copy, and there is no need to configure anything before the language features start working.
The special case is Yarn 2. For yarn2 users, at version v2.0.0-rc.36 or later, who want to use the local typescript module, the documentation gives a two step procedure. Run the command `yarn dlx @yarnpkg/sdks vim`, which generates a `.vim/coc-settings.json` with the content:
{
"eslint.packageManager": "yarn",
"eslint.nodePath": ".yarn/sdks",
"workspace.workspaceFolderCheckCwd": false,
"tsserver.tsdk": ".yarn/sdks/typescript/lib"
}The reason this exists is Yarn 2's Plug'n'Play model. There is no `node_modules` directory to resolve a module from, so the Yarn SDKs command generates a small set of shim files that make the package resolvable through a normal path. The `tsserver.tsdk` entry points the extension at that shim, and the generated file also carries the `eslint.packageManager` and `eslint.nodePath` keys.
The `workspace.workspaceFolderCheckCwd` setting is set to false, which is about how coc.nvim decides the root folder of a project, and is included because the SDK shim setup changes the working directory behaviour.
The other supported language is JSX and TSX, and there is a caveat about it. The extension supports javascript and typescript and jsx/tsx, and you need to make sure the buffer filetype is typescriptreact or javascriptreact for the React variants to work.
That filetype requirement is the kind of detail that produces a confusing first experience, because a.tsx file opened without the right filetype will parse but the React specific behaviour will not engage. The extension's activation events list in the manifest confirm which filetypes it registers for, including `onLanguage:javascriptreact`, `onLanguage:typescriptreact`, `onLanguage:typescript.tsx`, `onLanguage:jsx-tags` and `onLanguage:jsonc`.
The commands and the diagnostics settings
The extension contributes its own commands to the coc.nvim command list, and the set is worth reading because it covers the operations that are awkward to trigger otherwise.
`tsserver.reloadProjects` reloads the current project. `tsserver.openTsServerLog` opens the log file of tsserver, which is the first thing to look at when the language server is not behaving. `tsserver.goToProjectConfig` opens the project config file. `tsserver.restart` restarts tsserver. `tsserver.findAllFileReferences` finds file references across the project, which is a project-wide search rather than a symbol search within a file.
Two of the commands are unusual. `tsserver.watchBuild` runs `tsc --watch` for the current project using vim's job feature, so the extension can drive a watch build alongside the language server. And `tsserver.executeAutofix` fixes autofixable problems in the current document, which applies the code actions the server has already computed rather than waiting for a manual quickfix.
`tsserver.goToSourceDefinition` goes to the source definition.
Among the configuration options, three affect what you see in the editor rather than how the server runs. `tsserver.reportStyleChecksAsWarnings` reports style checks as warnings, defaulting to true, so a lint-style complaint from the compiler does not shout at you the way an error does. `tsserver.locale` sets the locale used to report JavaScript and TypeScript errors, with options from auto through de, es, en, fr, it, ja, ko, ru, zh-CN and zh-TW, defaulting to follow VS Code's locale.
Two settings control the server's resources. `tsserver.maxTsServerMemory` sets the maximum amount of memory to allocate to the TypeScript server process, defaulting to 3072, which is worth raising on a large codebase and worth lowering on a small machine. And `tsserver.enableTracing` enables tracing of TS server performance to a directory, with the documentation warning that the log may contain file paths, source code and other potentially sensitive information from your project.
That warning is the kind of thing to take seriously before enabling tracing on a client codebase and then uploading the output to a bug report.
The `tsserver.log` and `tsserver.trace.server` settings are the two log levels, with tsserver's own log offering normal, terse, verbose, requestTime and off, and the trace level offering off, messages and verbose.
Inlay hints, watchman and the parts that need something else
Three features depend on the wider environment rather than on the extension alone, and it is useful to know which is which.
Inlay hints support uses the virtual text feature of neovim, and it requires TypeScript 4.4.0 or newer and Neovim 0.4.0 or newer, and it is enabled by options starting with `typescript.inlayHints` or `javascript.inlayHints`.
The virtual text requirement is the interesting constraint. Inlay hints are rendered as text on the line, and in Neovim that needs the virtual text API, which arrived in 0.4. In older Neovim the feature simply cannot work, and the extension says so rather than degrading quietly.
Rename imports on file rename requires watchman installed in your $PATH. That is a real dependency on a Facebook tool, and it is there because watching a directory tree for renames across a project is exactly the kind of thing watchman does well. The alternative is not watching, which means a rename leaves the import graph stale until something else notices.
The `tsserver.watchOptions` setting configures which watching strategies are used to keep track of files and directories, and it requires TypeScript 3.8 or newer in the workspace. So there are two file watching mechanisms in play, the server's own and tsserver's, and the setting decides which of tsserver's strategies are on.
There is also a socket path option, `tsserver.socketPath`, for connecting to an already running tsserver over a socket rather than spawning one. The documentation is precise about the requirement: the socket should be opened already, using tools like socat to start the server and pipe messages to the standard output of tsserver, and when it exists, the command line arguments related to configurations will not work. The path format is like `127.0.0.1:7070`, defaulting to null.
That option exists for a specific scenario. If you want one tsserver shared across several editor instances, or a server running in a container that the editor connects to, the spawned process is the wrong model and a socket is the right one. The trade is that you lose the command line configuration, because the process was already started.
The `tsserver.pluginPaths` setting adds paths to discover TypeScript Language Service plugins, and `tsserver.implicitProjectConfig.checkJs` enables checkJs for the implicit project, which is the settings you get when there is no tsconfig.json in the folder.
Editorial conclusion
coc-tsserver fits a Vim or Neovim developer working on a TypeScript codebase who wants editor parity with VS Code without switching, because the extension is a fork of the extension VS Code bundles, so the feature set tracks the real one. Skip it if you want a self-contained LSP setup with no node_modules, since this extension runs the TypeScript server as a separate process, and skip it if you only need syntax highlighting, which the documentation says is not supported and points at other plugins for. Before you install, decide which TypeScript version you want, because the resolution order changed in v2.0.0 and the default is the bundled one, and note that inlay hints need TypeScript 4.4 or newer and Neovim 0.4 or newer. The last push was on 2026-10-03 and the package version is 2.4.1.
Frequently asked questions
What is coc-tsserver?
It is a coc.nvim extension that drives Microsoft's tsserver language service, forked from the typescript-language-features extension bundled with VSCode, so Neovim gets completion, go to definition, refactoring, call hierarchy and inlay hints.
How do I install coc-tsserver in Neovim?
Run `:CocInstall coc-tsserver` inside vim or neovim. Yarn 2 users who want the workspace TypeScript module run `yarn dlx @yarnpkg/sdks vim` to generate a `.vim/coc-settings.json` pointing tsserver.tsdk at the SDK shim.
Which TypeScript version does coc-tsserver use?
From v2.0.0 the tsserver module is resolved first from the global `tsserver.tsdk` configuration, with the bundled module used when not found, and the workspace's own typescript module is used when `tsserver.useLocalTsdk` is enabled. The command `:CocCommand tsserver.chooseVersion` overrides the choice.
What does coc-tsserver need for inlay hints?
TypeScript 4.4.0 or newer and Neovim 0.4.0 or newer, since it uses Neovim's virtual text feature, and it is enabled by the `typescript.inlayHints` and `javascript.inlayHints` options.
Does coc-tsserver do syntax highlighting?
No. File type detection and syntax highlighting are not supported by the extension, and the documentation directs you to other vim plugins for those, since they are a filetype and treesitter concern rather than a language service one.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/neoclide-coc-tsserver)Was this useful?