Skip to main content
This configuration provides comprehensive TypeScript/JavaScript support using the tsgo LSP server (Microsoft’s native TypeScript server), along with formatters and linters.

Language server

The configuration uses tsgo instead of ts_ls:
-- From lua/plugins/lsp/init.lua:45
vim.lsp.enable({
  "tsgo", -- TypeScript/JavaScript (native server from Microsoft)
})
tsgo is Microsoft’s native TypeScript server. To switch to ts_ls, rename after/lsp/tsgo.lua to tsgo.lua.bak and ts_ls.lua.bak to ts_ls.lua.

tsgo configuration

Custom configuration is in after/lsp/tsgo.lua:

Memory and capabilities

-- From after/lsp/tsgo.lua:3
return {
  capabilities = {
    workspace = {
      didChangeWatchedFiles = {
        dynamicRegistration = true,
      },
    },
  },
  init_options = {
    maxTsServerMemory = 8192,
  },
}

Completions and auto-imports

-- From after/lsp/tsgo.lua:16
suggest = {
  autoImports = true,
  includeAutomaticOptionalChainCompletions = true,
  includeCompletionsForImportStatements = true,
  classMemberSnippets = { enabled = true },
  objectLiteralMethodSnippets = { enabled = true },
}

Import preferences

-- From after/lsp/tsgo.lua:25
preferences = {
  importModuleSpecifierPreference = "shortest", -- "shortest" | "project-relative" | "relative" | "non-relative"
  importModuleSpecifierEnding = "auto", -- "auto" | "minimal" | "index" | "js"
  includePackageJsonAutoImports = "auto",
  preferTypeOnlyAutoImports = false,
  quoteStyle = "auto", -- "auto" | "double" | "single"
}

Organize imports

-- From after/lsp/tsgo.lua:32
organizeImports = {
  typeOrder = "last", -- "auto" | "last" | "first" | "inline"
  caseSensitivity = "auto", -- "auto" | "caseInsensitive" | "caseSensitive"
}

Code lens

-- From after/lsp/tsgo.lua:42
implementationsCodeLens = {
  enabled = true,
  showOnInterfaceMethods = true,
  showOnAllClassMethods = true,
},
referencesCodeLens = {
  enabled = true,
  showOnAllFunctions = true,
}
Code lens shows:
  • Implementation counts on interfaces and classes
  • Reference counts on functions
Trigger code lens with <leader>cl.

Inlay hints

-- From after/lsp/tsgo.lua:52
inlayHints = {
  parameterNames = {
    enabled = "all", -- "none" | "literals" | "all"
    suppressWhenArgumentMatchesName = false,
  },
  parameterTypes = {
    enabled = true,
  },
  variableTypes = {
    enabled = true,
    suppressWhenTypeMatchesName = false,
  },
  propertyDeclarationTypes = {
    enabled = true,
  },
  functionLikeReturnTypes = {
    enabled = true,
  },
  enumMemberValues = {
    enabled = true,
  },
}
Inlay hints are disabled by default. Toggle them with <leader>ih.

Error translation

TypeScript errors are translated to plain English:
-- From lua/plugins/languages/typescript.lua:2
{
  "dmmulroy/ts-error-translator.nvim",
  enabled = true,
  opts = {
    auto_attach = true,
    servers = {
      "tsgo",
    },
  },
}
This plugin automatically translates cryptic TypeScript errors like:
TS2322: Type 'string' is not assignable to type 'number'.
Into more understandable explanations.

Formatting

TypeScript/JavaScript files use Biome or Prettier:
-- From lua/plugins/formatter.lua:54
javascript = { "biome-check", "prettier", stop_after_first = true },
javascriptreact = { "biome-check", "prettier", stop_after_first = true },
typescript = { "biome-check", "prettier", stop_after_first = true },
typescriptreact = { "biome-check", "prettier", stop_after_first = true },

Biome vs Prettier

Biome

  • Used when biome.json exists
  • Faster than Prettier
  • Also handles linting
  • Runs safe fixes automatically

Prettier

  • Fallback when no Biome config
  • Widely adopted standard
  • More configuration options
  • Supports more file types
Installation:
npm install -g @biomejs/biome prettier

Linting

Linting uses eslint_d:
-- From lua/plugins/linting.lua:74
javascript = { "eslint_d" },
javascriptreact = { "eslint_d" },
typescript = { "eslint_d" },
typescriptreact = { "eslint_d" },
Trigger linting with <leader>ll. Installation:
npm install -g eslint_d
If you have biome.json, the Biome LSP also provides linting diagnostics automatically.

Biome LSP

For projects using Biome, the Biome LSP is also enabled:
-- From lua/plugins/lsp/init.lua:47
vim.lsp.enable({
  "biome", -- Biome (linting/formatting for JS/TS/JSON - only activates with biome.json)
})
The Biome LSP:
  • Only activates when biome.json exists
  • Provides real-time linting
  • Offers quick fixes for lint errors
  • Works alongside tsgo

Angular support

Angular projects get additional language service:
-- From lua/plugins/lsp/init.lua:46
vim.lsp.enable({
  "angularls", -- Angular Language Service (template intelligence)
})
Requires @angular/language-server to be installed:
npm install -g @angular/language-server

Common workflows

Auto-import

  1. Type a symbol that’s not imported
  2. Press ga or <leader>ca for code actions
  3. Select “Add import from…”

Organize imports

  1. Press ga or <leader>ca
  2. Select “Organize Imports”
Or configure it to run on save via LSP.

Rename symbol

  1. Place cursor on symbol
  2. Press <leader>rn
  3. Type new name
  4. Press Enter
Renames across all files in the project.

View references

  1. Place cursor on symbol
  2. Press gr (uses Snacks picker)
Shows all references with preview.

Go to definition

  1. Place cursor on symbol
  2. Press gd (uses Snacks picker)
Jumps to definition or shows list if multiple.

Keymaps

All standard LSP keymaps work:
KeymapAction
KHover documentation
<C-k>Signature help
gdGo to definition
grFind references
giGo to implementation
gtGo to type definition
gaCode action
<leader>caCode action (enhanced UI)
<leader>rnRename symbol
<leader>clRun code lens
<leader>ihToggle inlay hints
<leader>fbFormat buffer
<leader>llLint file
]d / [dNext/prev diagnostic

Installation summary

1

Install TypeScript and tsserver

npm install -g typescript-language-server typescript
2

Install formatters

npm install -g @biomejs/biome prettier
3

Install linters

npm install -g eslint_d
4

Optional: Angular support

npm install -g @angular/language-server
5

Optional: Biome LSP

Create biome.json in your project root to enable Biome LSP.

Troubleshooting

Server not starting

  1. Check TypeScript is installed: typescript-language-server --version
  2. Run :LspInfoCustom to see client status
  3. Check logs: :LspLog

Auto-imports not working

  1. Verify autoImports is enabled in after/lsp/tsgo.lua:18
  2. Check if you’re in a TypeScript project (has tsconfig.json)
  3. Restart LSP: :LspRestart

Slow performance

  1. Check maxTsServerMemory in after/lsp/tsgo.lua:12
  2. Disable inlay hints: <leader>ih
  3. Check if project is very large - consider tsconfig.json optimizations

Formatting not working

  1. Check formatter is installed: biome --version or prettier --version
  2. Run :ConformInfo to see formatter status
  3. For Biome, ensure biome.json exists if you want Biome formatting

Next steps

Go configuration

Configure Go language support

Lua configuration

Configure Lua language support

Formatting

Learn more about formatters

Linting

Learn more about linters

Build docs developers (and LLMs) love