If you’re like me, you prefer Vue over React, Neovim over VSCode, and you have a love-hate relationship with TypeScript. The pain you must go through to have Neovim work efficiently with Vue 3 and TypeScript isn’t helping either.
I’ll spare any long-winded tale about how much hang-banging there was to make it all work. Long story short, the Volar 2 Vue language server no longer has TypeScript support built in. So, with it, you have to use the ts_ls TypeScript LSP, a.k.a. typescript-language-server. (Yeah, the names and aliases throw me off too.)
Let’s just jump into the Neovim config I had to put it to have them play together peacefully, marching together hand in hand towards peace.
The LSP config
Keep in mind, I forked an NvChad starter config with which does some things automatically, like loading mappings and pre-made LSP configs.
⚠️ : Heads up! Two months ago,
require('lspconfig')was deprecated in favour ofvim.lsp.config()andvim.lsp.enable()in Nvim 0.11. The code below was for the earlier. To see an example usage of the new API, see the current version of this file.
-- ~/.config/nvim/lua/configs/lspconfig.lua
-- Loaded automatically by NvChad
-- Load defaults i.e lua_lsp
require("nvchad.configs.lspconfig").defaults()
local lspconfig = require "lspconfig"
local nvlsp = require "nvchad.configs.lspconfig"
-- Dynamically point to the path of @vue/language-server
-- which contains @vue/typescript-plugin
local vue_typescript_plugin =
vim.fn.expand(vim.fn.stdpath "data" .. "/mason/packages/vue-language-server/node_modules/@vue/language-server")
-- Set up ts_ls LSP with @vue/typescript-plugin
lspconfig.ts_ls.setup {
on_attach = nvlsp.on_attach,
on_init = nvlsp.on_init,
capabilities = nvlsp.capabilities,
init_options = {
plugins = {
{
name = "@vue/typescript-plugin",
location = vue_typescript_plugin,
languages = { "vue" },
},
},
},
filetypes = {
"javascript",
"typescript",
"vue",
},
settings = {
typescript = {
tsserver = {
useSyntaxServer = false,
},
inlayHints = {
includeInlayParameterNameHints = "all",
includeInlayParameterNameHintsWhenArgumentMatchesName = true,
includeInlayFunctionParameterTypeHints = true,
includeInlayVariableTypeHints = true,
includeInlayVariableTypeHintsWhenTypeMatchesName = true,
includeInlayPropertyDeclarationTypeHints = true,
includeInlayFunctionLikeReturnTypeHints = true,
includeInlayEnumMemberValueHints = true,
},
},
},
}
The config above was inspired by the official nvim-lspconfig docs by Neovim and this article by Dan Walsh.
Showing messages
By default, diagnostic messages about your code will appear as a single line, which may get too long to read.
To have them appear in a floating box which only show up when your cursor is on the offending line, you can try adding the following in lspconfig.lua:
vim.diagnostic.config {
virtual_text = false, -- Show text after diagnostics
signs = true,
update_in_insert = false,
underline = true,
severity_sort = false,
float = true,
}
-- Show diagnostics text on cursor hold
local lspGroup = vim.api.nvim_create_augroup("Lsp", { clear = true })
vim.api.nvim_create_autocmd("CursorHold", {
command = "lua vim.diagnostic.open_float()",
group = lspGroup,
})
Thanks to Naborisk for providing the two parts for the above. They’re another avid user of Neovim and requested not to be asked how much time was needed to figure that out. (Us Neovim users can all understand the embarassment of spending days on end tweaking our config.)
Complete configuration
To view the entire setup, you can also view the complete lspconfig.lua file as of this article and its latest version.
Now, go ahead, and be happy go lucky with all your Vue 3 and TypeScript action.
