Skip to content

How to configure VS Code for type checking in a uv project

VS Code doesn’t show type errors by default. Adding inline diagnostics takes two steps: installing a type checker as a dev dependency with uv, and installing the matching VS Code extension. This guide covers two routes for a uv-managed project: ty with the official ty extension, and mypy with Microsoft’s Mypy Type Checker extension.

This guide assumes a uv-managed project with a .venv directory. If you haven’t set one up yet, see create your first Python project.

Pick the right extension

ty extension mypy extension
Extension ID astral-sh.ty ms-python.mypy-type-checker
Replaces Pylance Yes (by default) No
Completions source ty Pylance
Config in pyproject.toml [tool.ty] [tool.mypy]
Best for New projects on the Astral toolchain Projects already on mypy

If your project already runs mypy in CI, start with the mypy extension so the editor matches the pipeline. If you’re adding type checking for the first time, the ty extension gives you a type checker and language server in one install.

Set up the ty extension

Add ty as a dev dependency:

uv add --dev ty

Install the ty extension (astral-sh.ty) from the VS Code Marketplace. Its default importStrategy is fromEnvironment, so it finds the ty binary in .venv automatically after uv sync.

Keep Pylance or let ty replace it

Pylance (bundled with the Python extension) and ty are both language servers: each provides completions, go-to-definition, hover documentation, and type-error diagnostics. Running both produces duplicate diagnostics.

The ty extension resolves this by disabling Pylance when it activates, setting python.languageServer to None. Keep this default when you want ty to own every language-server feature.

To keep Pylance’s IntelliSense alongside ty’s type checking, switch ty into type-checking-only mode:

.vscode/settings.json
{
  "python.languageServer": "Pylance",
  "ty.disableLanguageServices": true
}

With ty.disableLanguageServices set to true, ty reports type errors as diagnostics but leaves completions and hover to Pylance. Use this when adopting ty incrementally.

Check the whole workspace

By default, ty reports diagnostics only for open files (ty.diagnosticMode is openFilesOnly). To see type errors across the whole project, set it to workspace:

.vscode/settings.json
{
  "ty.diagnosticMode": "workspace"
}

Point ty at the venv interpreter

ty discovers .venv/ without extra configuration. If the environment lives in a non-standard location, or imports stay unresolved after uv sync, set ty.interpreter (a list whose first entry is used):

.vscode/settings.json
{
  "ty.interpreter": [".venv/bin/python"]
}

Note

ty is in beta as of 2026. If Pylance provides a feature ty doesn’t yet support, run them together in type-checking-only mode rather than letting ty disable Pylance.

Set up the mypy extension

mypy uses the Mypy Type Checker extension (ms-python.mypy-type-checker). It only reports diagnostics, so Pylance keeps handling IntelliSense and no language-server conflict arises.

Add mypy as a dev dependency:

uv add --dev mypy

Then install the extension from the Marketplace and configure it:

.vscode/settings.json
{
  "mypy-type-checker.importStrategy": "fromEnvironment",
  "mypy-type-checker.reportingScope": "workspace"
}

Use the venv mypy, not the bundled copy

The extension defaults importStrategy to useBundled, shipping its own mypy. For a uv project that causes two problems: the bundled mypy can differ from the version pinned in pyproject.toml, and it can’t see third-party type stubs installed with uv add --dev. Setting importStrategy to fromEnvironment makes the extension use the mypy in the active environment, which is the .venv uv creates. Run uv sync before opening VS Code so mypy is present.

reportingScope: "workspace" reports errors across the whole project instead of only open files (the default is file).

Daemon mode is already on

The extension defaults preferDaemon to true, keeping a dmypy process alive between saves so incremental checks are fast. No extra configuration is needed. If the daemon gets into a bad state after a dependency change, stop it and let VS Code restart it on the next check:

uv run dmypy stop

Set the working directory in a monorepo

The extension runs mypy with ${workspaceFolder} as the working directory, matching the project root where pyproject.toml lives. When the mypy configuration lives in a subdirectory, point cwd at it:

.vscode/settings.json
{
  "mypy-type-checker.cwd": "${workspaceFolder}/backend"
}

cwd also accepts ${fileDirname} (run from the checked file’s directory) and ${nearestConfig} (run from the nearest ancestor directory containing a mypy configuration file).

Resolve imports across a uv workspace

In a uv workspace, packages that import from sibling members can trip false “unresolved import” warnings. When Pylance handles completions (the mypy route, or ty in type-checking-only mode), add the source roots:

.vscode/settings.json
{
  "python.analysis.extraPaths": ["packages/pkg-a/src", "packages/pkg-b/src"]
}

For mypy’s own resolution, add the same roots to pyproject.toml:

pyproject.toml
[tool.mypy]
mypy_path = "packages/pkg-a/src"

For multiple paths, separate them with colons on macOS/Linux or semicolons on Windows.

Use Pylance’s built-in type checking

Pylance includes Pyright-based type checking without a separate project dependency. Enable it with:

.vscode/settings.json
{
  "python.analysis.typeCheckingMode": "standard"
}

The modes are off (default), basic, standard, and strict. standard checks annotated code and infers types for most patterns; strict enables every check, matching Pyright with --strict.

Pylance’s checker doesn’t read [tool.mypy] or [tool.ty] from pyproject.toml; configuration goes into python.analysis.* settings or a pyrightconfig.json file.

Tip

Pylance’s built-in checking is a good starting point when evaluating type checking before committing to a tool. Once you settle on mypy or ty, switch to the dedicated extension for tighter pyproject.toml integration.

Restart the language server after switching setups

After changing the interpreter or switching extensions, the language server can hold stale state. Reset it from the Command Palette:

  • ty: ty: Restart server
  • mypy: Mypy: Restart Server

Learn More

Last updated on