The Language Service is the layer of the TypeScript codebase that wraps the compiler to provide rich, editor-facing features. It handles requests at specific source positions (completions, definitions, references, diagnostics, refactors, etc.) and manages the lifecycle of Program objects on behalf of an editor host.
This page covers the top-level design: the LanguageService and LanguageServiceHost interfaces, createLanguageService, DocumentRegistry, and the service-layer node/symbol wrappers. Individual editor features are documented in their own sub-pages:
For the language server that drives editors via a JSON protocol, see tsserver (5).
The compiler (scanner → parser → binder → checker → emitter) operates as a batch pipeline on a Program. The Language Service sits on top of that pipeline and provides an incremental, position-aware API for editors.
Overall architecture diagram:
Sources: src/services/services.ts1-362 src/services/types.ts1-80
LanguageServiceDefined in src/services/types.ts the LanguageService interface is the primary API surface consumed by editors. It is grouped into several functional areas:
| Category | Representative Methods |
|---|---|
| Diagnostics | getSyntacticDiagnostics, getSemanticDiagnostics, getSuggestionDiagnostics |
| Completions | getCompletionsAtPosition, getCompletionEntryDetails, getCompletionEntrySymbol |
| Hover / Quick Info | getQuickInfoAtPosition |
| Go to Definition | getDefinitionAtPosition, getDefinitionAndBoundSpan, getTypeDefinitionAtPosition, getImplementationAtPosition |
| References | getReferencesAtPosition, findReferences, getDocumentHighlights, getFileReferences |
| Rename | getRenameInfo, findRenameLocations |
| Signature Help | getSignatureHelpItems |
| Navigation | getNavigateToItems, getNavigationBarItems, getNavigationTree, getOutliningSpans |
| Call Hierarchy | prepareCallHierarchy, provideCallHierarchyIncomingCalls, provideCallHierarchyOutgoingCalls |
| Formatting | getFormattingEditsForRange, getFormattingEditsForDocument, getFormattingEditsAfterKeystroke |
| Code Fixes | getCodeFixesAtPosition, getCombinedCodeFix, getSupportedCodeFixes |
| Refactors | getApplicableRefactors, getEditsForRefactor, getMoveToRefactoringFileSuggestions |
| Imports | organizeImports, getEditsForFileRename |
| JSDoc | getDocCommentTemplateAtPosition |
| Inlay Hints | provideInlayHints |
| Emit | getEmitOutput |
| Paste | preparePasteEdits, getPasteEdits |
| Misc | getProgram, dispose, toLineColumnOffset, getBraceMatchingAtPosition |
Sources: src/services/types.ts1-500
LanguageServiceHostThe client (editor or tsserver) implements LanguageServiceHost to give the LanguageService access to the file system, compiler settings, and cancellation tokens. The interface is defined in src/services/types.ts
Key methods the host must implement:
| Method | Purpose |
|---|---|
getCompilationSettings() | Returns CompilerOptions for the current project |
getScriptFileNames() | Returns the list of files in the project |
getScriptVersion(fileName) | Returns an opaque version string for a file |
getScriptSnapshot(fileName) | Returns an IScriptSnapshot for a file's current content |
getCurrentDirectory() | Used for resolving relative paths |
getDefaultLibFileName(options) | Locates the built-in .d.ts library |
fileExists, readFile, readDirectory, directoryExists | File system access |
getCancellationToken() | Returns a HostCancellationToken for cooperative cancellation |
getProjectVersion() | Optional; allows the service to skip program rebuilds when unchanged |
Optional methods enrich behavior:
resolveModuleNames / resolveTypeReferenceDirectives — custom module resolutiongetDocumentPositionMapper — source map integrationgetLocalizedDiagnosticMessages — localized error textSources: src/services/types.ts1-500
LanguageServiceModeThe LanguageServiceMode enum (in src/services/types.ts) controls how much of the compiler pipeline is enabled:
| Value | Description |
|---|---|
Semantic | Full mode. Type checking, all semantic features available. |
PartialSemantic | Partial type resolution. Used for some background operations. |
Syntactic | Syntax only. No type checker created. Only syntactic features (outline, bracket match, syntactic classifications) are available. |
LanguageServiceMode is passed as part of the options to createLanguageService.
createLanguageServicecreateLanguageService in src/services/services.ts is the factory function that constructs a LanguageService implementation. Signature (simplified):
createLanguageService(
host: LanguageServiceHost,
documentRegistry?: DocumentRegistry,
syntaxOnlyOrLanguageServiceMode?: boolean | LanguageServiceMode
): LanguageService
Internally it:
HostCache that canonicalizes file names and caches snapshots.synchronizeHostData() to detect host changes and rebuild the Program when the project version or file contents have changed.SourceFile instances from the DocumentRegistry, which allows sharing parsed files across multiple Program instances (important for tsserver, which manages many projects).createProgram from src/compiler/program.ts to produce or update the active Program.Program and its TypeChecker.synchronizeHostData flow:
Sources: src/services/services.ts1200-1600
DocumentRegistryThe DocumentRegistry is a shared cache of SourceFile objects, created by createDocumentRegistry in src/services/services.ts It is passed to createLanguageService and is also used directly by tsserver's ProjectService.
Purpose: When multiple projects (or multiple language service instances for the same project) share files (e.g., lib.d.ts, common utilities), parsing that file once and reusing the SourceFile across all Program instances saves memory and CPU.
Key API:
| Method | Description |
|---|---|
acquireDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind?) | Parse and cache a new SourceFile, or return an existing one with an incremented reference count. |
updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind?) | Incrementally update a cached SourceFile for a new version. |
releaseDocument(fileName, compilationSettings, scriptKind?, impliedNodeFormat?) | Decrement the reference count; evict when it reaches zero. |
getKeyForCompilationSettings(settings) | Returns a DocumentRegistryBucketKey used to bucket files by their compiler settings (two programs with different settings need separate SourceFile instances). |
Document sharing diagram:
Sources: src/services/services.ts1000-1100 src/server/editorServices.ts1-200
The compiler internally uses lightweight plain objects for AST nodes and symbols. The language service augments these with richer methods by overriding the objectAllocator (defined in src/compiler/utilities.ts) to use service-specific class implementations.
Class hierarchy diagram:
Sources: src/services/services.ts364-800
The key distinction versus compiler-internal objects:
NodeObject implements the public Node interface with getStart(), getEnd(), getChildren(), and getFullText(). The compiler's internal representation does not expose these.SymbolObject adds getDocumentationComment() and getJsDocTags(), which traverse JSDoc comments — expensive operations that the compiler core avoids.SourceFileObject.getNamedDeclarations() builds a name → declaration map used by navigation features.These are installed at service startup via setObjectAllocator:
setObjectAllocator({
getNodeConstructor: () => NodeObject,
getTokenConstructor: () => TokenObject,
getIdentifierConstructor: () => IdentifierObject,
getPrivateIdentifierConstructor: () => PrivateIdentifierObject,
getSourceFileConstructor: () => SourceFileObject,
getSymbolConstructor: () => SymbolObject,
getTypeConstructor: () => TypeObject,
getSignatureConstructor: () => SignatureObject,
...
})
Sources: src/services/services.ts800-900
Each editor feature is implemented in a dedicated module under src/services/. The LanguageService implementation in services.ts delegates to these modules:
Feature module mapping:
Sources: src/services/services.ts1-60 src/services/completions.ts1-60 src/services/findAllReferences.ts1-60 src/services/goToDefinition.ts1-30
The language service does not replace the compiler — it drives it. Every time a file changes, synchronizeHostData either reuses the existing Program or calls createProgram to build a new one. The TypeChecker is obtained from the current Program via program.getTypeChecker() and is the source of all semantic answers (types, symbols, diagnostics).
Sources: src/services/services.ts1200-1700 src/services/completions.ts1-100
Long-running operations (type checking, find-all-references) cooperatively check for cancellation through CancellationToken. The host provides a HostCancellationToken which the service wraps internally. Cancellation throws an OperationCanceledException, which the caller is expected to catch.
Sources: src/services/types.ts1-50 src/services/services.ts1200-1300
The language service is part of the TypeScript public API exposed through the typescript npm package. The stable public types are emitted to tests/baselines/reference/api/typescript.d.ts and include LanguageService, LanguageServiceHost, DocumentRegistry, IScriptSnapshot, UserPreferences, and all feature result types (CompletionInfo, DefinitionInfo, ReferenceEntry, etc.).
For documentation of the public compiler API as a whole, see Public Compiler API (7).
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.