DEV Community

Cover image for [SOLVED] Vue 3 + TypeScript + Inlay Hint support in NeoVim
Dan Walsh
Dan Walsh

Posted on

5

[SOLVED] Vue 3 + TypeScript + Inlay Hint support in NeoVim

It would be an understatement to say that getting stable Vue 3 language server support in NeoVim over the last 9-12 months has been smooth sailing for me, as evidenced by this lengthy GitHub issue: volar v2 no longer works.

I'd almost given up on finding "the right" solution. Everywhere I looked, others had "solved" the issue in different ways: they were using the vtsls TypeScript LSP wrapper instead of ts_ls, or they were using coc.nvim, or the now-archived null-ls.nvim. But nowhere could I simply find a reliable configuration for a Vue language server configured natively in NeoVim.

But today, I've finally got it working, and it looks like it should be for good. Massive thanks to Johnson Chu and GR3YH4TT3R93. 👏

Now I can finally say:

Frodo from Lord of the Rings saying,

TLDR, just gimme the config so I can write some sweet Vue code with that LSP-goodness

Since you asked so nicely, sure. Here are the volar and ts_ls server configs for nvim-lspconfig. If you're using something like kickstart.nvim, you'll want to add these entries to your servers table:

local servers = {
  -- Vue 3        
  volar = {},
  -- TypeScript
  ts_ls = {
    filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' },
    init_options = {
      plugins = {
        {
          name = '@vue/typescript-plugin',
          location = vim.fn.stdpath 'data' .. '/mason/packages/vue-language-server/node_modules/@vue/language-server',
          languages = { 'vue' },
        },
      },
    },
  },
  -- ...
}
Enter fullscreen mode Exit fullscreen mode

And for bonus points, here's the config if you want inlay hints. For this to work we need to disable hybrid mode:

local servers = {
  -- Vue 3        
  volar = {
    init_options = {
      vue = {
        hybridMode = false,
      },
    },
    settings = {
      typescript = {
        inlayHints = {
          enumMemberValues = {
            enabled = true,
          },
          functionLikeReturnTypes = {
            enabled = true,
          },
          propertyDeclarationTypes = {
            enabled = true,
          },
          parameterTypes = {
            enabled = true,
            suppressWhenArgumentMatchesName = true,
          },
          variableTypes = {
            enabled = true,
          },
        },
      },
    },
  },
  -- TypeScript
  ts_ls = {
    init_options = {
      plugins = {
        {
          name = '@vue/typescript-plugin',
          location = vim.fn.stdpath 'data' .. '/mason/packages/vue-language-server/node_modules/@vue/language-server',
          languages = { 'vue' },
        },
      },
    },
    settings = {
      typescript = {
        tsserver = {
          useSyntaxServer = false,
        },
        inlayHints = {
          includeInlayParameterNameHints = 'all',
          includeInlayParameterNameHintsWhenArgumentMatchesName = true,
          includeInlayFunctionParameterTypeHints = true,
          includeInlayVariableTypeHints = true,
          includeInlayVariableTypeHintsWhenTypeMatchesName = true,
          includeInlayPropertyDeclarationTypeHints = true,
          includeInlayFunctionLikeReturnTypeHints = true,
          includeInlayEnumMemberValueHints = true,
        },
      },
    },
  },
  -- ...
}
Enter fullscreen mode Exit fullscreen mode

Note: this assumes you are using mason.nvim to install and manage your LSPs.

With that in place, you should be able to do all the good things: code completion, go to definitions, rename symbols across files, and tell your co-workers you use NeoVim btw.

Winning

So how did we get here?

I'm glad you asked.

The previous Vue language server versions Vetur and Volar v1 were both troubled with memory duplication issues and the additional complexity of requiring the TypeScript Vue Plugin.

Both the TypeScript language server and the Vue language server were creating duplicate TypeScript abstract syntax trees (AST) in memory, which scaled with the size of your project.

While the TypeScript Vue Plugin had neat features like renaming symbols across .ts and .vue files, it added yet another layer of memory usage.

All of this lead to performance issues and tooling trade-offs, amounting to a sub-optimal development environment.

The solution at last

However, through much hard work and determination, Volar's author Johnson Chu delivered Volar v2 and a new "Hybrid mode" which solves these problems!

Johnson has a great write up on the history of these issues, including some useful visual aids. I would highly recommend you read it.

And it was GR3YH4TT3R93's support and patience in this GitHub issue thread, helping find the right configuration to support not just the newly released Volar v2, but inlay hint support as well.

Do your career a big favor. Join DEV. (The website you're on right now)

It takes one minute, it's free, and is worth it for your career.

Get started

Community matters

Top comments (4)

Collapse
 
anishdev127 profile image
Anish Kumar

can you provide for react js ? mine typescript suggestion are too much slow

Collapse
 
dowardev profile image
DowarDev

Thanks mate
LazyVim stopped working for my Vue projects a while ago, so I had to switch to VSCode.
I was missing vim.

Collapse
 
__ab6c8a profile image
Александр Костарев

Just registered to offer my thanks. With best regards from Kazan

Collapse
 
gaetanpinot profile image
Gaëtan Pinot

thanks

typescript

11 Tips That Make You a Better Typescript Programmer

1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields

...

Read the whole post now!

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay