The Program object is the top-level unit of a TypeScript compilation. It owns the full set of source files, compiler options, module resolution state, and the entry points for triggering type checking and emit. This page covers how a Program is created, how it manages source files, how module resolution is performed, and how syntactic and semantic diagnostics are collected.
For the components that Program coordinates — the binder and type checker — see 2.2 and 2.3 For how Program drives the emit pipeline see 2.4 For incremental and project builds built on top of Program, see 8
Program is defined in src/compiler/types.ts and is the central object a caller interacts with after parsing has finished. It aggregates source files, options, resolution results, and lazy-initialized subsystems.
| Method | Purpose |
|---|---|
getSourceFiles() | Returns all SourceFile objects loaded into the compilation |
getSourceFile(fileName) | Looks up a specific SourceFile by name |
getRootFileNames() | Returns the explicit roots passed to createProgram |
getCompilerOptions() | Returns the CompilerOptions in effect |
getTypeChecker() | Creates (once) and returns the TypeChecker |
emit(...) | Triggers the emitter; returns EmitResult |
getSyntacticDiagnostics(file?) | Parse-time errors; requires no type information |
getSemanticDiagnostics(file?) | Type errors; triggers full type checking |
getDeclarationDiagnostics(file?) | Errors produced during .d.ts generation |
getOptionsDiagnostics() | Errors in CompilerOptions values |
getGlobalDiagnostics() | Diagnostics applying to the whole program |
getConfigFileParsingDiagnostics() | Errors from tsconfig.json parsing |
getMissingFilePaths() | Files referenced but not found on disk |
isSourceFileFromExternalLibrary(file) | Whether a file comes from node_modules |
isSourceFileDefaultLibrary(file) | Whether a file is a default lib file |
Sources: src/compiler/types.ts
createProgram in src/compiler/program.ts is the public factory for Program. It accepts either an options bag or positional arguments for backward compatibility.
createProgram(rootNamesOrOptions, options?, host?, oldProgram?, configFileParsingDiagnostics?)
The CreateProgramOptions bag carries:
rootNames — explicit input file pathsoptions — CompilerOptionshost — optional CompilerHostoldProgram — previous Program for structure reuseconfigFileParsingDiagnostics — errors from tsconfig.json parsingCompilation unit diagram
Sources: src/compiler/program.ts328-350 src/compiler/types.ts
When an oldProgram is supplied, createProgram attempts to reuse its structure. The internal StructureIsReused enum tracks the outcome:
| Value | Meaning |
|---|---|
Not | Full rebuild required |
SafeModules | Source files that haven't changed can be kept; module resolutions must be rechecked |
Completely | The old program is fully reusable — options, files, and resolutions are unchanged |
This is checked via optionsHaveChanges and per-file comparisons. Complete reuse avoids re-parsing and re-binding all source files.
Sources: src/compiler/program.ts
CompilerHost is the I/O abstraction that Program uses to read files, resolve paths, and write outputs. It extends ModuleResolutionHost.
Core responsibilities
| Method | Description |
|---|---|
getSourceFile(fileName, options) | Read a file and parse it into a SourceFile |
getSourceFileByPath(fileName, path, options) | Variant using the canonical Path type |
writeFile(fileName, data, ...) | Write emitted output files |
getDefaultLibFileName(options) | Return the path to the default lib file |
getCurrentDirectory() | Provide the working directory |
getCanonicalFileName(name) | Normalize file names for case-insensitive systems |
useCaseSensitiveFileNames() | Indicate case sensitivity of the file system |
getNewLine() | Provide the line ending string for output |
fileExists(fileName) | Check whether a file exists |
readFile(fileName) | Read raw text of a file |
resolveModuleNameLiterals(...) | Override module resolution per-call |
resolveTypeReferenceDirectiveReferences(...) | Override type reference resolution |
getCancellationToken() | Provide an optional CancellationToken |
If no CompilerHost is provided, createProgram uses createCompilerHost which wraps sys (the platform's System object in src/compiler/sys.ts).
Host abstraction diagram
Sources: src/compiler/types.ts src/compiler/program.ts src/compiler/sys.ts
Starting from the rootNames, createProgram recursively discovers additional files through three mechanisms:
/// <reference path="..." /> and /// <reference types="..." />import, export from, require(), dynamic import()/// <reference types="..." /> and entries in typeRoots/types optionsEach discovered file is loaded via CompilerHost.getSourceFile, parsed, and added to the internal file map.
File inclusion tracking
The FileIncludeReason union type records why each file was added:
FileIncludeKind | Reason |
|---|---|
RootFile | Explicitly listed in rootNames |
SourceFromProjectReference | Included via a project reference |
ReferenceFile | Triple-slash <reference path> |
TypeReferenceDirective | Triple-slash <reference types> or types option |
LibFile | Default lib file |
AutomaticTypeDirectiveFile | Auto-discovered from node_modules/@types |
ImportedModuleNotFound | Module that failed to resolve |
Internally, Program maintains:
filesByName: Map<Path, SourceFile | false | undefined> — maps canonical Path to SourceFile, false (missing), or undefined (redirect)sourceFiles: SourceFile[] — ordered list of all included filesmissingFilePaths: Path[] — files that couldn't be foundThe Path type (a branded string) is the canonical, normalized, lower-cased file path used as the stable key.
File discovery flow
Sources: src/compiler/program.ts
CompilerOptions is a large interface in src/compiler/types.ts whose fields correspond directly to TSC command-line flags and tsconfig.json compilerOptions keys.
Key option groups and representative members:
| Group | Representative Options |
|---|---|
| Target & module | target, module, moduleResolution, moduleDetection |
| Type checking strictness | strict, strictNullChecks, noImplicitAny, strictFunctionTypes |
| Emit | outDir, outFile, declaration, declarationMap, sourceMap, emitDeclarationOnly |
| Library | lib, noLib, typeRoots, types |
| Path mapping | baseUrl, paths, rootDir, rootDirs |
| JavaScript support | allowJs, checkJs, maxNodeModuleJsDepth |
| Interop | esModuleInterop, allowSyntheticDefaultImports, isolatedModules |
| Project references | composite, incremental, tsBuildInfoFile |
Options are declared in src/compiler/commandLineParser.ts via optionDeclarations, which drives both the CLI parser and the tsconfig.json parser.
The function changesAffectingProgramStructure in src/compiler/program.ts determines which option changes require a completely new Program rather than reuse.
Sources: src/compiler/commandLineParser.ts src/compiler/types.ts src/compiler/program.ts
When the compiler encounters an import or require, it delegates to resolveModuleName in src/compiler/moduleNameResolver.ts The algorithm applied depends on CompilerOptions.moduleResolution:
ModuleResolutionKind | Behavior |
|---|---|
Classic | Legacy TypeScript resolution; searches relative paths then ambient modules |
Node10 (formerly Node) | Node.js CommonJS style; walks node_modules up the directory tree |
Node16 | Respects package.json exports and .mts/.cts extensions |
NodeNext | Alias for the latest Node16-compatible strategy |
Bundler | Package exports support without requiring extensions; for bundler environments |
To avoid redundant I/O, module resolution uses:
ModuleResolutionCache — caches ResolvedModuleWithFailedLookupLocations keyed on (moduleName, containingFile, resolutionMode)TypeReferenceDirectiveResolutionCache — caches type-reference resolutionsModeAwareCache<T> — a cache keyed on (name, mode) pairs, used when ESM and CJS resolution must be distinguishedEach resolved import produces a ResolvedModuleWithFailedLookupLocations:
resolvedModule?: ResolvedModuleFull — the successful result, including the resolved file name, extension, and optional package IDfailedLookupLocations: string[] — all paths that were probed but not foundModule resolution subsystem
Sources: src/compiler/moduleNameResolver.ts src/compiler/program.ts src/compiler/types.ts
Diagnostics in TypeScript are separated by phase to allow incremental and partial workflows.
| Collection Method | Phase | Requires Type Checker |
|---|---|---|
getSyntacticDiagnostics() | Parser errors | No |
getSemanticDiagnostics() | Type errors | Yes |
getDeclarationDiagnostics() | .d.ts generation errors | Yes |
getOptionsDiagnostics() | Invalid option values | No |
getGlobalDiagnostics() | Global type errors (e.g., duplicate lib defs) | Yes |
getConfigFileParsingDiagnostics() | tsconfig.json parse errors | No |
getSuggestionDiagnostics() | Non-error hints / quick-fix hints | Yes |
Each Diagnostic (defined in src/compiler/types.ts) carries:
category: DiagnosticCategory — Error, Warning, Message, Suggestioncode: number — unique error code from src/compiler/diagnosticMessages.jsonmessageText: string | DiagnosticMessageChainfile?: SourceFile — the file the error belongs tostart?: number, length?: number — character range within the filerelatedInformation?: DiagnosticRelatedInformation[] — secondary spansSyntactic diagnostics are collected by the parser and binder during createSourceFile and bindSourceFile. They are attached to the SourceFile.parseDiagnostics and SourceFile.bindDiagnostics arrays.
Semantic diagnostics are generated on-demand by TypeChecker.getDiagnostics. The first call to Program.getSemanticDiagnostics() triggers createTypeChecker and runs the checker over the requested file or all files.
Diagnostic flow
Sources: src/compiler/program.ts src/compiler/types.ts src/compiler/diagnosticMessages.json
The following shows how Program connects the major compiler subsystems:
| Function | File | Role |
|---|---|---|
createProgram | program.ts | Top-level factory |
createCompilerHost | program.ts | Default host wrapping sys |
createSourceFile | parser.ts | Parse text into SourceFile |
bindSourceFile | binder.ts | Assign symbols and flow nodes |
createTypeChecker | checker.ts | Construct the type checker |
emitFiles | emitter.ts | Drive the emit pipeline |
resolveModuleName | moduleNameResolver.ts | Resolve one import specifier |
findConfigFile | program.ts | Walk directories for tsconfig.json |
resolveTripleslashReference | program.ts | Convert <reference path> to absolute path |
Sources: src/compiler/program.ts src/compiler/types.ts src/compiler/emitter.ts src/compiler/moduleNameResolver.ts
The language service (see 4) creates and manages Program objects via createProgram whenever the set of open files or compiler options changes. It wraps the Program with a LanguageService that exposes editor features. The DocumentRegistry allows multiple language service instances to share parsed SourceFile objects, reducing memory overhead when the same files appear in multiple projects.
The tsserver project system (see 5.2) maintains one Program per Project (configured, inferred, or external), refreshing it when file changes are detected.
Sources: src/services/services.ts src/server/project.ts src/server/editorServices.ts
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.