Neovim has an LSP client built in. Since Neovim 0.11, vim.lsp.config() and vim.lsp.enable() set up a server in a few lines, and the nvim-lspconfig plugin supplies ready-made configs named ts_ls (for typescript-language-server) and vtsls. Both servers wrap TypeScript's own tsserver, so the errors in a .js file are the ones tsc reports, given the same TypeScript and the same jsconfig.json.
Install one server globally with npm, enable it, and the rest comes from your project: tsserver finds the nearest jsconfig.json above each file, so checkJs, strict and the other options apply as they do on the command line.
At a glance
| Editor | Neovim |
|---|---|
| What to install | nvim-lspconfig + a language server |
| What checks the code | Neovim's built-in LSP client talking to typescript-language-server (ts_ls) or vtsls, both of which run TypeScript's own server |
| Where its TypeScript comes from | Decided by the language server: typescript-language-server can use the workspace's TypeScript; vtsls uses its bundled copy unless told to use the workspace's |
| Reads | jsconfig.json, tsconfig.json |
| How this page was checked | Not run in Neovim for this page. The configuration is from Neovim's documentation (:help lsp) and the nvim-lspconfig ts_ls and vtsls configs linked below; what the servers report comes from TypeScript's language service, which the site's tests run. |
Enable a TypeScript language server
With nvim-lspconfig installed (it provides the server definitions), one line in init.lua starts ts_ls for JavaScript and TypeScript buffers. Install the server first: nvim-lspconfig's ts_ls config gives npm install -g typescript typescript-language-server, and its vtsls config gives npm install -g @vtsls/language-server.
-- Neovim 0.11+, with nvim-lspconfig installed for its server definitions
vim.lsp.enable('ts_ls') Use the project's TypeScript
The version matters because each TypeScript release adds and changes checks; the editor should run the version in your project's node_modules, which is what npm run lint runs. typescript-language-server reports where its TypeScript came from (the workspace, a configured tsserver.path, or its bundled copy), and the ts_ls config starts a project-local typescript-language-server from node_modules/.bin when there is one.
vtsls uses the TypeScript it bundles unless you set vtsls.autoUseWorkspaceTsdk, per its README:
vim.lsp.config('vtsls', {
settings = {
-- use node_modules/typescript instead of the copy vtsls ships with
vtsls = { autoUseWorkspaceTsdk = true },
},
})
vim.lsp.enable('vtsls') How the config is found
nvim-lspconfig decides the workspace root from lockfiles and .git, not from jsconfig.json. That is only the LSP workspace: inside it, TypeScript's server still looks for the nearest jsconfig.json or tsconfig.json above each file, so a project with several configs is checked with the right one per file.
What differs from tsc
Neovim shows the diagnostics for the buffers you open, through vim.diagnostic (configure how with vim.diagnostic.config()). Servers also pass on TypeScript's suggestions, such as unused names when noUnusedLocals is off and names marked @deprecated; tsc never prints those. Quick fixes come through code actions (the default gra mapping).
Make sure it matches tsc
Run npm run lint (or npx tsc -p jsconfig.json --pretty false) in a terminal, open one of the files it lists, and compare the codes. Errors in files you have not opened appear only in that output.
Gotchas
ts_lsandvtslsare alternatives; enabling both runs two servers and shows each error twice.- The nvim-lspconfig
ts_lsnotes say it needs a TypeScript version below 7 for now.
Sources
- LSP (:help lsp) · Neovim documentation
- nvim-lspconfig: lsp/ts_ls.lua · nvim-lspconfig on GitHub
- nvim-lspconfig: lsp/vtsls.lua · nvim-lspconfig on GitHub
- typescript-language-server · typescript-language-server on GitHub
- vtsls · vtsls on GitHub
Last reviewed 20 October 2026.