---
title: "How to configure VS Code for TypeScript projects"
slug: "configure-vscode-for-typescript-projects"
category: "howto"
tags: ["howto", "vscode", "typescript", "editor", "tooling", "dx", "linting"]
status: "stable"
last_updated: 2026-05-14
summary: "Configure VS Code with workspace settings, extensions, and TypeScript project references for accurate type checking on large projects."
related: ["[[coding/typescript]]", "[[comparisons/eslint-vs-biome]]", "[[comparisons/typescript-vs-flow]]", "[[comparisons/swc-vs-babel]]", "[[tooling/github]]", "[[coding/general-principles]]", "[[comparisons/jest-vs-vitest]]"]
---

## Overview

VS Code works out of the box with TypeScript but degrades on large projects without explicit configuration. This guide adds a `.vscode/settings.json` that pins the workspace TypeScript version, wires the formatter, configures import organization, and reduces editor noise from irrelevant files. The result is accurate type errors, fast go-to-definition, and consistent formatting on save. See [[coding/typescript]] for the `tsconfig.json` conventions.

## Prerequisites

- VS Code with the default TypeScript extension (`ms-vscode.vscode-typescript-next` for the latest engine, or the built-in for stability).
- A `tsconfig.json` at the project root.
- TypeScript installed as a dev dependency: `npm add -D typescript` or `pnpm add -D typescript`.

## Steps

### 1. Create `.vscode/settings.json`

`.vscode/settings.json` applies workspace-level settings that override user defaults. Commit this file so all contributors get consistent settings.

```json
{
  "typescript.tsdk": "node_modules/typescript/lib",
  "typescript.enablePromptUseWorkspaceTsdk": true,
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "biomejs.biome",
  "[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
  "[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" },
  "editor.codeActionsOnSave": {
    "source.organizeImports": "explicit",
    "source.fixAll.biome": "explicit"
  },
  "typescript.preferences.importModuleSpecifier": "relative",
  "typescript.updateImportsOnFileMove.enabled": "always",
  "files.exclude": {
    "node_modules": true,
    "dist": true,
    ".next": true,
    "public": true
  },
  "search.exclude": {
    "node_modules": true,
    "dist": true,
    "pnpm-lock.yaml": true
  }
}
```

Replace `biomejs.biome` with `esbenp.prettier-vscode` if the project uses Prettier instead of Biome.

### 2. Pin the workspace TypeScript version

`"typescript.tsdk": "node_modules/typescript/lib"` tells VS Code to use the project's installed TypeScript version rather than the built-in one. This ensures the editor and CI use the same compiler.

On first open, VS Code prompts to use the workspace TypeScript. Click **Allow** or enable `typescript.enablePromptUseWorkspaceTsdk` to automate this.

Verify the active version in the status bar at the bottom right. It should match `typescript` in `package.json`.

### 3. Install recommended extensions

Create `.vscode/extensions.json` to prompt contributors to install the right extensions.

```json
{
  "recommendations": [
    "biomejs.biome",
    "ms-vscode.vscode-typescript-next",
    "bradlc.vscode-tailwindcss",
    "dbaeumer.vscode-eslint"
  ]
}
```

Contributors see a prompt to install recommended extensions when they open the project.

### 4. Configure `tsconfig.json` for editor performance

On large projects, exclude directories that the editor does not need to type-check.

```json
{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "target": "ES2022",
    "moduleResolution": "bundler",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "exclude": ["node_modules", "dist", ".next", "public"]
}
```

`"moduleResolution": "bundler"` matches Vite and Next.js module resolution behavior. See [[comparisons/swc-vs-babel]] for how this affects the build.

### 5. Use project references for monorepos

In a monorepo, each package should have its own `tsconfig.json` and the root should have a `tsconfig.json` with `references`. This allows VS Code to provide accurate cross-package type checking.

```json
// Root tsconfig.json
{
  "files": [],
  "references": [
    { "path": "./packages/ui" },
    { "path": "./packages/api" },
    { "path": "./apps/web" }
  ]
}
```

Run `tsc --build` to compile with project references. VS Code uses the references to resolve imports across packages.

## Verify it worked

Open a TypeScript file and confirm:

1. Hovering a variable shows the inferred type.
2. Saving auto-formats the file and organizes imports.
3. The TypeScript version in the status bar matches the project's installed version.
4. Renaming a symbol across files updates all references automatically.

```bash
# Confirm workspace TypeScript version
cat node_modules/typescript/package.json | grep '"version"'
```

The version should match what VS Code reports in the status bar.

## Common errors

- **Editor uses wrong TypeScript version**: `typescript.tsdk` is not set, or the path is wrong. Verify `node_modules/typescript/lib` exists with `ls node_modules/typescript/lib/typescript.js`.
- **Format on save does nothing**: the formatter extension is not installed, or `"editor.defaultFormatter"` is set to an extension ID that does not match the installed extension. Check **View > Extensions** for the correct ID.
- **Imports not organizing**: `source.organizeImports` requires the TypeScript language service to be active on the file. Ensure the file's language mode is TypeScript, not JavaScript.
- **Go-to-definition jumps to `.d.ts` instead of source**: add `"declarationMap": true` to `tsconfig.json`. This generates source maps for declarations so go-to-definition resolves to the original `.ts` file.
- **Type errors in editor not matching `tsc` output**: the editor is using a different `tsconfig.json` than `tsc`. Add `"typescript.tsconfig.autoDetect": "on"` and check which config the status bar reports.

## Related

- [[coding/typescript]]
- [[comparisons/eslint-vs-biome]]
- [[comparisons/typescript-vs-flow]]
- [[comparisons/swc-vs-babel]]
- [[tooling/github]]
- [[coding/general-principles]]
- [[comparisons/jest-vs-vitest]]
