This page introduces tsserver as the long-running editor server process, describes its overall architecture, and explains how its major components relate to each other. For detailed coverage of the communication protocol, see tsserver Protocol. For project lifecycle management, see Project Management. For automatic type acquisition, see Automatic Type Acquisition. For the underlying language services that tsserver exposes, see Language Service.
tsserver is a long-running Node.js process that exposes the TypeScript Language Service to editors and IDEs over a line-delimited JSON protocol. Instead of re-launching the compiler on every keystroke, the editor spawns a single tsserver process at startup, keeps it alive for the duration of the editing session, and exchanges request/response/event messages through its standard input and output streams.
All rich editing features that editors provide—completions, diagnostics, go-to-definition, rename, code fixes—are ultimately served by tsserver calling into the language service on behalf of the client.
tsserver component hierarchy
Sources: src/server/session.ts1-110 src/server/editorServices.ts1-200 src/server/project.ts1-70
tsserver is launched by editors as a child process. The canonical entry point is src/server/server.ts (not included in the file set above, but referenced by the build system). It constructs a Session and calls session.listen() to start the read loop.
The initialization sequence is:
ServerHost implementation (wrapping sys) is provided to Session.Session constructs a ProjectService, which in turn creates a DocumentRegistry and sets up file watchers.open request for a file, ProjectService locates or creates the appropriate Project (see Project Management).LanguageService backed by a fresh or reused Program.Initialization flow
Sources: src/server/editorServices.ts197-210 src/server/project.ts25-30 src/server/session.ts1-50
All messages are JSON objects, one per line, transmitted over stdio. There are three message shapes:
| Shape | Key field | Direction | Description |
|---|---|---|---|
Request | "type": "request" | Editor → tsserver | A command with a sequence number and optional arguments |
Response | "type": "response" | tsserver → Editor | Result for a specific request sequence number |
Event | "type": "event" | tsserver → Editor | Unsolicited notification (e.g. diagnostics ready) |
The seq field links responses to requests. Responses include a success boolean and a body containing the result.
Example request/response pair (conceptual):
The full set of commands is defined in the CommandTypes enum in src/server/protocol.ts1-120 (also reflected in tests/baselines/reference/api/typescript.d.ts49-126).
Session (src/server/session.ts)Session owns the read loop and the command dispatch table. It:
ServerHost.protocol.Request.command string.protocol.Response.ThrottledOperations.The handler methods are named after their commands (e.g. getCompletions, getDefinition, getSemanticDiagnosticsSync) and delegate to ProjectService to find the active project and then call through to the project's LanguageService.
ProjectService (src/server/editorServices.ts)ProjectService is the central coordinator. It manages:
ScriptInfo objects).Project instances.tsconfig.json files and source files.Key constants defined here:
maxProgramSizeForNonTsFiles = 20 MB — threshold above which JS files are excluded from a program.maxFileSize = 4 MB — per-file size limit.Events emitted by ProjectService (as string constants):
| Constant | Value | Meaning |
|---|---|---|
ProjectsUpdatedInBackgroundEvent | "projectsUpdatedInBackground" | Background update finished |
ProjectLoadingStartEvent | "projectLoadingStart" | Project starting to load |
ProjectLoadingFinishEvent | "projectLoadingFinish" | Project finished loading |
ConfigFileDiagEvent | "configFileDiag" | tsconfig.json diagnostics available |
ProjectLanguageServiceStateEvent | "projectLanguageServiceState" | Language service enabled/disabled |
LargeFileReferencedEvent | "largeFileReferenced" | A file exceeded maxFileSize |
Sources: src/server/editorServices.ts198-210
ScriptInfo (src/server/scriptInfo.ts)Each open or referenced file is represented as a ScriptInfo. It stores:
NormalizedPath).ScriptKind (TS, JS, TSX, etc.).ScriptInfo acts as the shared, version-tracked document store that all projects access through the LanguageServiceHost interface.
Three concrete project types inherit from the abstract Project base:
| Type | Description |
|---|---|
ConfiguredProject | Backed by a tsconfig.json / jsconfig.json file |
InferredProject | Created for files that have no tsconfig.json |
ExternalProject | Client-defined project (used by non-VS Code integrations) |
AutoImportProviderProject | Auxiliary project used to compute auto-import completions |
Each project owns a LanguageService instance and a DocumentRegistry (shared across projects to avoid parsing the same file twice).
How a completions request travels through tsserver
Sources: src/server/session.ts1-220 src/server/editorServices.ts1-200 src/server/project.ts1-70
tsserver does not duplicate language service or compiler logic. The dependency chain is strictly layered:
src/compiler/ implements all parsing, type-checking, and emit logic.src/services/services.ts wraps the compiler in the LanguageService interface, adding editor-oriented features (completions, references, refactors, etc.).src/server/ wraps the language service in a protocol layer, adding project management, file watching, and incremental update handling.This layering means tsserver can be thought of as a process host for the language service. Any code that can call createLanguageService from src/services/services.ts1-362 can use the same features tsserver exposes.
Sources: src/services/services.ts361-362 src/server/project.ts25-30
ProjectService supports loading compiler plugins, which are Node.js modules that can wrap or replace the LanguageService for a project. Plugins are declared in tsconfig.json under compilerOptions.plugins. The ConfigurePlugin command (CommandTypes.ConfigurePlugin) allows the editor to pass plugin-specific options at runtime.
Plugin loading is handled inside Project in src/server/project.ts and deferred until the language service is first activated.
Unlike most requests, diagnostics are not returned synchronously in response to a specific request. The workflow is:
Geterr request (or GeterrForProject) listing the files it wants errors for.semanticDiag, syntacticDiag, and suggestionDiag events (not responses).This allows the editor to remain responsive while the type checker works in the background.
Sources: src/server/session.ts1-100 tests/baselines/reference/api/typescript.d.ts49-126
| Page | Topic |
|---|---|
| tsserver Protocol | Full JSON message format, key command reference, Session dispatch details |
| Project Management | ProjectService, ConfiguredProject, InferredProject, ExternalProject lifecycle |
| Automatic Type Acquisition | TypingsInstaller, jsTyping, @types discovery and npm integration |
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.