Jesse A. Green / notebook

TypeScript Administrator & Developer Guide

Generated May 2026 from microsoft/TypeScript at f350b52

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

1. Architecture Overview

TypeScript is a statically-typed superset of JavaScript that compiles to plain JavaScript. It consists of three major subsystems: a compiler (tsc) that performs type checking and code emission, a language service that powers IDE features like IntelliSense and refactoring, and a language server (tsserver) that exposes the language service over a JSON-based protocol to editors.

Architecture Diagram

                            ┌─────────────────────────────────────┐
                            │           tsconfig.json             │
                            │        (project configuration)      │
                            └──────────────┬──────────────────────┘
                                           │
         ┌─────────────────────────────────┼─────────────────────────────┐
         │                                 │                             │
         ▼                                 ▼                             ▼
┌─────────────────┐             ┌───────────────────┐          ┌─────────────────┐
│    tsc (CLI)    │             │  Language Service  │          │    tsserver      │
│  src/tsc/       │             │  src/services/     │          │  src/server/     │
│                 │             │                    │          │  src/tsserver/   │
│  executeCommand │             │  completions       │          │                  │
│  Line()         │             │  diagnostics       │◄────────►│  Session         │
│                 │             │  refactoring       │          │  (JSON protocol) │
│                 │             │  navigation        │          │                  │
└────────┬────────┘             │  formatting        │          │  Projects        │
         │                      │  code fixes        │          │  (configured,    │
         │                      └────────┬───────────┘          │   inferred,      │
         │                               │                      │   external)      │
         │              ┌────────────────┘                      └─────────────────┘
         │              │
         ▼              ▼
┌───────────────────────────────────────────┐
│            Compiler Core                  │
│            src/compiler/                  │
│                                           │
│  Source Text                              │
│    │                                      │
│    ▼                                      │
│  Scanner (scanner.ts)                     │
│    │  tokens                              │
│    ▼                                      │
│  Parser (parser.ts)                       │
│    │  AST (SourceFile)                    │
│    ▼                                      │
│  Binder (binder.ts)                       │
│    │  Symbols + Flow graph                │
│    ▼                                      │
│  Checker (checker.ts)                     │
│    │  Type-checked AST                    │
│    ▼                                      │
│  Emitter (emitter.ts)                     │
│    │  + Transformers (transformers/)      │
│    ▼                                      │
│  Output (.js, .d.ts, .map)               │
└───────────────────────────────────────────┘
         │
         ▼
┌───────────────────────────────────────────┐
│         Standard Library (src/lib/)       │
│  lib.es5.d.ts, lib.es2015.d.ts,         │
│  lib.dom.d.ts, lib.esnext.d.ts, ...     │
│  (107 declaration files)                 │
└───────────────────────────────────────────┘

Component Inventory

Component Path Role
Compiler core src/compiler/ (36 files, 3.3M chars) Scanner, parser, binder, checker, emitter, transformers, module resolution, program management
Language service src/services/ (38 files, 1.6M chars) IDE features: completions, diagnostics, refactoring, navigation, formatting, code fixes
Language server src/server/ (13 files, 789K chars) tsserver: session management, project management, protocol handlers
Server entry src/tsserver/ (3 files, 33K chars) Node.js tsserver entry point, IPC setup, logging
CLI entry src/tsc/ (1 file, 584 chars) tsc command-line entry point
Library API src/typescript/ (1 file, 638 chars) Public API re-export entry point
Standard library src/lib/ (107 files, 565K chars) Built-in type definitions (ES5–ESNext, DOM, WebWorker, etc.)
Typings installer src/typingsInstaller/ + src/typingsInstallerCore/ Automatic @types package discovery and installation
JS typing src/jsTyping/ (3 files, 25K chars) Type acquisition heuristics for JavaScript files
Watch guard src/watchGuard/ (1 file, 737 chars) Subprocess that tests if fs.watch is safe for a directory
Deprecated compat src/deprecatedCompat/ (2 files, 9.2K chars) Shims for deprecated API functions
Test harness src/harness/ (23 files, 752K chars) Test infrastructure: fourslash, baselines, virtual file system
Test runner src/testRunner/ (6 files, 68K chars) Mocha-based test execution, parallel worker

Technology Stack

Layer Technology
Language TypeScript (self-hosted)
Runtime Node.js ≥ 14.17
Build hereby (task runner), esbuild (bundling)
Testing Mocha, chai, custom fourslash test framework
Linting ESLint with typescript-eslint, custom ESLint rules
Formatting dprint with @dprint/typescript
Coverage c8, monocart-coverage-reports
CI/CD Azure Pipelines
Package npm (published as typescript)
License Apache-2.0

Note

TypeScript is self-hosted: the compiler is written in TypeScript and compiled by a previous version of itself. The devDependencies include typescript: "^6.0.2" for bootstrapping.


2. System Requirements

Requirement Minimum Recommended
Node.js 14.17 22.x (LTS)
npm 6.x 8.x+
OS Windows, macOS, Linux Any
Memory 512 MB 4 GB+ (for large projects)
Disk 50 MB (installed) 100 MB+ (with build artifacts)

Development Requirements

Tool Version Purpose
Node.js 22.22.0 (Volta-pinned) Runtime and build
npm 8.19.4 (Volta-pinned) Package management
hereby ≥ 1.14.0 Task runner (replaces Gulp)
esbuild ≥ 0.27.4 Fast bundling for build
dprint ≥ 0.49.1 Code formatting
Mocha ≥ 10.8.2 Test framework
Playwright ≥ 1.58.2 Browser-based tests

3. Configuration Reference

TypeScript configuration is defined in tsconfig.json (or jsconfig.json for JavaScript-only projects). The compiler reads this file to determine compilation options, file scope, and project structure.

Configuration Files

File Format Location Purpose
tsconfig.json JSON with comments Project root Primary project configuration
jsconfig.json JSON with comments Project root JavaScript project configuration (alias for tsconfig.json with allowJs: true)
tsconfig.*.json JSON with comments Project root Variant configs (e.g., tsconfig.build.json, tsconfig.test.json)

Configuration Hierarchy

Configurations support inheritance via extends:

{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "outDir": "./dist"
  }
}

Important

Relative paths in extends are resolved relative to the file containing the extends property. The ${configDir} template variable can be used in path-valued options to reference the directory of the current config file.

Compiler Options by Category

File Layout

Option Type Default Description
rootDir string (inferred from inputs) Root directory of input files; controls output directory structure
outDir string (same as input) Output directory for all emitted files
outFile string (none) Concatenate and emit output to a single file (AMD/SystemJS only)
rootDirs string[] (none) Virtual root directories for module resolution
declarationDir string (same as outDir) Output directory for declaration files

Environment Settings

Option Type Default Description
target string es5 ECMAScript target version: es5, es2015–es2023, esnext
module string varies by target Module system: nodenext, esnext, commonjs, amd, system, umd
moduleResolution string varies by module Resolution strategy: nodenext, node16, bundler, node10, classic
lib string[] (target-dependent) Library declaration files to include
types string[] (all @types) @types packages to include
typeRoots string[] ["./node_modules/@types"] Directories to search for type declarations

Strict Type-Checking

Option Type Default Description
strict boolean false Enable all strict type-checking options
strictNullChecks boolean strict null and undefined are distinct types
strictFunctionTypes boolean strict Contravariant function parameter checking
strictBindCallApply boolean strict Check bind, call, apply argument types
strictPropertyInitialization boolean strict Class properties must be initialized or declared with !
noImplicitAny boolean strict Error on expressions with implied any type
noImplicitThis boolean strict Error on this with implied any type
alwaysStrict boolean strict Parse in strict mode and emit "use strict"
useUnknownInCatchVariables boolean strict Type catch clause variables as unknown
exactOptionalPropertyTypes boolean false Differentiate between undefined and missing optional properties
noUncheckedIndexedAccess boolean false Add undefined to index signature access results

Module Options

Option Type Default Description
moduleDetection string auto How files are treated as modules: auto, legacy, force
esModuleInterop boolean false Emit interop helpers for CommonJS/ESM compatibility
verbatimModuleSyntax boolean false Enforce import syntax matches output; replaces importsNotUsedAsValues
isolatedModules boolean false Ensure each file can be transpiled independently
isolatedDeclarations boolean false Ensure declarations can be generated per-file
allowSyntheticDefaultImports boolean varies Allow import x from 'module' for modules without default export
resolveJsonModule boolean false Allow importing .json files
resolvePackageJsonExports boolean varies Use package.json exports field for resolution
resolvePackageJsonImports boolean varies Use package.json imports field for resolution
allowImportingTsExtensions boolean false Allow .ts/.tsx in import specifiers (requires noEmit or emitDeclarationOnly)
rewriteRelativeImportExtensions boolean false Rewrite .ts extensions to .js in output
allowArbitraryExtensions boolean false Allow importing files with arbitrary extensions
noUncheckedSideEffectImports boolean false Check that side-effect imports resolve

Path Mapping

Option Type Default Description
baseUrl string (none) Base directory for non-relative module names
paths object (none) Path alias mappings (requires baseUrl or relative to tsconfig.json)
rootDirs string[] (none) Virtual combined directory for resolution

Emit Options

Option Type Default Description
declaration boolean false Generate .d.ts declaration files
declarationMap boolean false Generate source maps for declarations
emitDeclarationOnly boolean false Only emit declarations, not JavaScript
sourceMap boolean false Generate .js.map source map files
inlineSourceMap boolean false Embed source maps in .js files
inlineSources boolean false Embed TypeScript source in source maps
noEmit boolean false Do not emit any output files
noEmitOnError boolean false Do not emit if there are type errors
removeComments boolean false Strip comments from output
importHelpers boolean false Import emit helpers from tslib
downlevelIteration boolean false Full iterator protocol support in ES5 output
newLine string platform Line ending: crlf or lf
preserveConstEnums boolean false Keep const enum declarations in output
emitBOM boolean false Emit UTF-8 BOM
emitDecoratorMetadata boolean false Emit design-type metadata for decorators
experimentalDecorators boolean false Enable legacy decorator support

JavaScript Support

Option Type Default Description
allowJs boolean false Allow JavaScript files in the project
checkJs boolean false Type-check JavaScript files
maxNodeModuleJsDepth number 0 Max depth to search node_modules for JS type info

JSX

Option Type Default Description
jsx string (none) JSX support: react, react-jsx, react-jsxdev, preserve, react-native
jsxFactory string React.createElement JSX factory function
jsxFragmentFactory string React.Fragment JSX fragment factory
jsxImportSource string react Module for JSX factory import (with react-jsx)

Project References

Option Type Default Description
composite boolean false Enable constraints for project references
incremental boolean composite Save build state for incremental compilation
tsBuildInfoFile string .tsbuildinfo Path for incremental build state file
disableReferencedProjectLoad boolean false Lazy-load referenced projects
disableSolutionSearching boolean false Opt out of multi-project find-references

Completeness

Option Type Default Description
skipLibCheck boolean false Skip type checking all .d.ts files
skipDefaultLibCheck boolean false Skip type checking built-in .d.ts files
forceConsistentCasingInFileNames boolean false Disallow inconsistent file name casing
noErrorTruncation boolean false Show full type in error messages
preserveSymlinks boolean false Do not resolve symlinks to their real path

Watch Options

{
  "watchOptions": {
    "watchFile": "useFsEvents",
    "watchDirectory": "useFsEvents",
    "fallbackPolling": "dynamicPriorityPolling",
    "synchronousWatchDirectory": true,
    "excludeDirectories": ["**/node_modules", "dist"]
  }
}
Option Values Description
watchFile useFsEvents, useFsEventsOnParentDirectory, dynamicPriorityPolling, fixedPollingInterval, priorityPollingInterval, fixedChunkSizePolling File watching strategy
watchDirectory useFsEvents, dynamicPriorityPolling, fixedPollingInterval, fixedChunkSizePolling Directory watching strategy
fallbackPolling dynamicPriorityPolling, fixedInterval, priorityInterval, fixedChunkSize Fallback when fs events unavailable
synchronousWatchDirectory boolean Defer watch directory notifications
excludeDirectories string[] Directories excluded from watching
excludeFiles string[] Files excluded from watching

Tip

On Linux systems with many files, you may hit the inotify watch limit. Either increase it (sysctl fs.inotify.max_user_watches=524288) or use polling-based watch strategies.

Environment Variables

Variable Purpose Source
TSC_WATCHFILE Override file watching strategy src/compiler/sys.ts
TSC_NONPOLLING_WATCHER Use non-polling file watcher src/compiler/sys.ts
TSC_WATCHDIRECTORY Override directory watching strategy src/compiler/sys.ts
TSS_LOG tsserver log file path and verbosity src/tsserver/nodeServer.ts
TSS_TRACE tsserver trace file path src/tsserver/nodeServer.ts
NODE_ENV When set to development, enables source maps in tsc/tsserver src/tsc/tsc.ts, src/tsserver/server.ts
NODE_INSPECTOR_IPC Detected to identify debugger attachment src/compiler/sys.ts
VSCODE_INSPECTOR_OPTIONS Detected to identify VS Code debugger src/compiler/sys.ts

Important

TSS_LOG accepts a path (e.g., TSS_LOG="-logToFile true -file /tmp/tsserver.log -level verbose"). This is essential for diagnosing language server issues. Log levels: terse, normal, requestTime, verbose.

File Inclusion/Exclusion

Property Type Default Description
include string[] ["**/*"] Glob patterns for source files
exclude string[] ["node_modules", "bower_components", "jspm_packages", outDir] Glob patterns to exclude
files string[] (none) Explicit file list (no globs, must exist)

4. Deployment & Scaling

Publishing TypeScript as a Package

TypeScript itself is published to npm as the typescript package. The published artifact contains:

Directory Contents
bin/ tsc and tsserver CLI entry scripts
lib/ Bundled compiler (typescript.js), language service, standard library .d.ts files
lib/typescript.d.ts Public API type definitions

The package.json defines:

{
  "main": "./lib/typescript.js",
  "typings": "./lib/typescript.d.ts",
  "bin": {
    "tsc": "./bin/tsc",
    "tsserver": "./bin/tsserver"
  }
}

Release Process

TypeScript uses Azure Pipelines for CI/CD:

  1. Build pipeline (azure-pipelines.release.yml): triggers on release-* branches, runs tests, produces a tarball artifact
  2. Publish pipeline (azure-pipelines.release-publish.yml): manual trigger, publishes the tarball to npm with a tag (dev, beta, rc, latest) and creates a GitHub release

Publish tags:

Tag Purpose
dev Nightly development builds
beta Pre-release beta versions
rc Release candidates
latest Stable releases

Embedding TypeScript

TypeScript can be used as a library:

import * as ts from "typescript";

const program = ts.createProgram(["src/index.ts"], {
  target: ts.ScriptTarget.ES2020,
  module: ts.ModuleKind.NodeNext,
});

const diagnostics = ts.getPreEmitDiagnostics(program);
diagnostics.forEach(d => {
  console.log(ts.flattenDiagnosticMessageText(d.messageText, "\n"));
});

The public API is exported from src/typescript/typescript.ts which re-exports all public symbols from the compiler and services.

Note

The TypeScript API is large and not all of it is documented. Many internal types are accessible but marked @internal and may change between versions without notice.


5. Operations

Build System

TypeScript uses hereby as its task runner (replacing the legacy Gulp setup via .gulp.js compatibility shim):

npx hereby <task>

Key build tasks (from package.json scripts):

Command Task
npm run build:compiler hereby local — build the compiler
npm run build:tests hereby tests — build the test infrastructure
npm run build Build compiler + tests
npm run test hereby runtests-parallel --light=false — run all tests
npm run lint hereby lint — run ESLint
npm run format dprint fmt — format all source
npm run knip hereby knip — detect unused exports/dependencies
npm run clean hereby clean — remove build artifacts
npm run setup-hooks node scripts/link-hooks.mjs — install git hooks

Tip

Use npm run build:tests:notypecheck (hereby tests --no-typecheck) for faster test builds when you know the types are correct.

Code Coverage

Coverage is configured via .c8rc.json:

{
  "reporter": ["lcovonly", "cobertura", "v8", "v8-json", "codecov"],
  "src": "src",
  "include": ["src/**", "built/local/**"],
  "exclude": ["**/node_modules/**"],
  "mergeAsync": true
}

Language Server Operations

The tsserver language server is the backbone of IDE integration. It manages project state and responds to editor requests over a JSON-based protocol.

tsserver Command-Line Arguments

Argument Purpose
--globalPlugins <plugins> Comma-separated list of global language service plugins
--pluginProbeLocations <paths> Comma-separated paths to probe for plugins
--allowLocalPluginLoads Allow loading plugins from node_modules local to the project
--useSingleInferredProject Use a single inferred project for all open files
--useInferredProjectPerProjectRoot Create separate inferred projects per root
--suppressDiagnosticEvents Suppress diagnostic event notifications
--noGetErrOnBackgroundUpdate Don't request errors after background project updates
--canUseWatchEvents Enable editor-provided file watching events
--cancellationPipeName <name> Named pipe for request cancellation
--locale <locale> Display language locale

Typings Installer Arguments

Argument Purpose
--globalCacheLocation <path> Global cache for @types packages
--npmLocation <path> Path to npm executable
--validateDefaultNpmLocation Verify the default npm path exists
--typingSafeListLocation <path> Path to typing safe list
--typesMapLocation <path> Path to types map
--logFile <path> Log file for typings installer

Note

The typings installer runs as a child process of tsserver. It discovers JavaScript files that need @types packages and installs them automatically via npm. The types registry is at node_modules/types-registry/index.json in the global cache.


6. Performance

Compilation Performance

TypeScript uses several strategies to optimize compilation speed:

Strategy Mechanism
Incremental compilation .tsbuildinfo file caches dependency graph and per-file hashes; only changed files and their dependents are re-checked
Project references --build mode compiles referenced projects in dependency order, reusing up-to-date outputs
Lazy evaluation The checker evaluates types on demand rather than eagerly computing all types
Interned strings String interning reduces memory allocation for repeated identifiers
Tracing --generateTrace <dir> produces Chrome DevTools-compatible trace files for profiling

Memory Optimization

For large projects exceeding memory limits:

  1. Split into smaller projects using project references
  2. Enable skipLibCheck to avoid checking third-party declarations
  3. Use disableReferencedProjectLoad for lazy-loading referenced projects
  4. Limit lib to only the libraries actually needed
  5. Exclude test and generated files from the main tsconfig.json

Profiling

npx tsc --generateTrace trace_output

Open trace_output/trace.json in chrome://tracing or the Chrome DevTools Performance tab to identify slow phases (binding, checking, emitting).

Tip

The --extendedDiagnostics flag prints timing breakdown for each compilation phase (I/O, parsing, binding, checking, emitting) and memory usage.

npx tsc --extendedDiagnostics
Files:           1523
Lines of Library:  41023
Lines of Definitions: 128402
Lines of TypeScript:  89234
Nodes of Library:  172048
Nodes of Definitions: 498123
Nodes of TypeScript:  412893
Identifiers:     321034
Symbols:         198234
Types:           89102
Instantiations:  234891
Memory used:     312412K
Assignability cache size: 98234
Identity cache size:      1234
Subtype cache size:       4521
Strict subtype cache size: 2345
I/O Read time:   0.12s
Parse time:      0.45s
ResolveModule time: 0.08s
ResolveTypeReference time: 0.02s
Program time:    0.89s
Bind time:       0.23s
Check time:      2.34s
Emit time:       0.56s
Total time:      4.02s

7. Security

Supply Chain Security

TypeScript's package.json defines "browser" overrides that disable Node.js-specific modules (fs, os, path, crypto, buffer, inspector, perf_hooks, source-map-support) when TypeScript is loaded in a browser context. This prevents accidental exposure of server-side APIs.

Configuration Security

  • skipLibCheck: While it improves performance, it skips type checking of declaration files, which means type errors in third-party packages won't be caught
  • allowJs + checkJs: When enabled on untrusted JavaScript, TypeScript's JSDoc parser processes all JSDoc comments, which could contain misleading type assertions
  • plugins: Language service plugins run in the tsserver process with full Node.js access. Only install plugins from trusted sources
  • allowLocalPluginLoads: When tsserver is started with this flag, it loads plugins from node_modules relative to the project, which could be a vector for malicious packages

Warning

Language service plugins execute arbitrary JavaScript in the editor's TypeScript process. Review any plugins before enabling --allowLocalPluginLoads in your editor configuration.

Source Map Security

Source maps (sourceMap, inlineSourceMap, inlineSources) can expose original TypeScript source code. In production deployments, either disable source maps or ensure they are not served publicly.


8. Developer Internals

Repository Structure

microsoft/TypeScript/
├── src/
│   ├── compiler/          # Core compiler (36 files, 3.3M chars)
│   │   ├── scanner.ts     # Lexical analysis → token stream
│   │   ├── parser.ts      # Syntax analysis → AST (SourceFile)
│   │   ├── binder.ts      # Symbol creation + control flow graph
│   │   ├── checker.ts     # Type checking (the largest file in the project)
│   │   ├── emitter.ts     # Code generation orchestration
│   │   ├── transformer.ts # AST transformation pipeline
│   │   ├── transformers/  # Individual transformers (ES2015→ES5, JSX, etc.)
│   │   ├── types.ts       # All AST node types and compiler types
│   │   ├── program.ts     # Program creation and management
│   │   ├── sys.ts         # System abstraction (file I/O, watch)
│   │   ├── commandLineParser.ts  # CLI argument parsing
│   │   ├── moduleNameResolver.ts # Module resolution algorithms
│   │   ├── core.ts        # Core utilities (Queue, sorting, etc.)
│   │   ├── utilities.ts   # Internal utility functions
│   │   ├── utilitiesPublic.ts    # Public utility functions
│   │   ├── diagnosticInformationMap.generated.ts  # All diagnostic messages
│   │   ├── tracing.ts     # Performance tracing
│   │   └── factory/       # AST node factory functions
│   ├── services/          # Language service (38 files, 1.6M chars)
│   │   ├── services.ts    # LanguageService implementation
│   │   ├── completions.ts # IntelliSense completion provider
│   │   ├── goToDefinition.ts
│   │   ├── findAllReferences.ts
│   │   ├── rename.ts
│   │   ├── signatureHelp.ts
│   │   ├── documentHighlights.ts
│   │   ├── callHierarchy.ts
│   │   ├── inlayHints.ts
│   │   ├── navigateTo.ts
│   │   ├── navigationBar.ts
│   │   ├── organizeImports.ts
│   │   ├── outliningElementsCollector.ts
│   │   ├── smartSelection.ts
│   │   ├── formatting/    # Code formatting rules engine
│   │   │   ├── rules.ts   # Formatting rule definitions
│   │   │   └── ...
│   │   ├── refactors/     # Refactoring providers
│   │   ├── codefixes/     # Code fix providers
│   │   └── classifier.ts  # Semantic/syntactic classification
│   ├── server/            # Language server (13 files, 789K chars)
│   │   ├── session.ts     # Request/response handler (protocol implementation)
│   │   ├── project.ts     # Project types and management
│   │   ├── editorServices.ts # Editor integration services
│   │   ├── protocol.ts    # Wire protocol type definitions
│   │   ├── utilitiesPublic.ts # Server utility functions
│   │   └── ...
│   ├── tsserver/          # Server entry point (3 files)
│   │   ├── server.ts      # Main entry + startup
│   │   ├── nodeServer.ts  # Node.js system initialization + logging
│   │   └── common.ts      # Shared types
│   ├── tsc/               # CLI entry point (1 file)
│   │   └── tsc.ts         # Calls ts.executeCommandLine()
│   ├── typescript/        # Library entry (1 file)
│   │   └── typescript.ts  # Re-exports all public API
│   ├── lib/               # Standard library (107 .d.ts files)
│   ├── jsTyping/          # JS type acquisition
│   ├── typingsInstaller/  # @types installer (Node.js)
│   ├── typingsInstallerCore/ # @types installer core logic
│   ├── watchGuard/        # fs.watch safety check subprocess
│   ├── deprecatedCompat/  # Deprecated API shims
│   ├── harness/           # Test harness (23 files)
│   └── testRunner/        # Test runner (6 files)
├── tests/                 # Test suite (80K+ files, mostly baselines)
│   ├── cases/             # Test input files
│   ├── baselines/         # Expected output baselines
│   └── lib/               # Test library stubs
├── scripts/               # Build and maintenance scripts
│   ├── eslint/            # Custom ESLint rules for the project
│   └── hooks/             # Git hooks
├── lib/                   # Published library output (not in source)
├── .c8rc.json             # Coverage configuration
├── .gulp.js               # hereby compatibility shim
├── package.json           # Package manifest
└── azure-pipelines.*.yml  # CI/CD pipeline definitions

Architecture Deep Dive

Compiler Pipeline

The TypeScript compiler processes source code through five sequential phases:

1. Scanner (scanner.ts) Converts source text into a stream of tokens. The scanner is re-entrant and supports rescanning for template literals and JSX. It handles Unicode, regular expressions, and comment parsing.

2. Parser (parser.ts) Consumes the token stream and produces an Abstract Syntax Tree (AST). Each source file becomes a SourceFile node. The parser handles:

  • Full ECMAScript grammar + TypeScript extensions (type annotations, enums, decorators, etc.)
  • JSX syntax
  • JSDoc comment parsing for JavaScript type checking
  • Error recovery (produces a valid AST even for malformed input)

3. Binder (binder.ts) Walks the AST and creates Symbol objects that connect declarations to their uses. The binder also constructs the control flow graph used for narrowing (type guards, null checks). Key responsibilities:

  • Symbol table construction (mapping names to declarations)
  • Control flow graph for type narrowing
  • Container/scope identification
  • Module and namespace resolution
  • Export assignment tracking

4. Checker (checker.ts) The type checker is the largest and most complex component. It performs:

  • Type inference (return types, generic instantiation, contextual typing)
  • Type compatibility checking (assignability, subtype, identity)
  • Overload resolution
  • Generic type parameter inference and constraint checking
  • Control-flow-based type narrowing (typeof, instanceof, truthiness, discriminated unions)
  • Excess property checking
  • JSX element type checking
  • Diagnostic message generation for type errors

5. Emitter (emitter.ts) + Transformers (transformer.ts, transformers/) Converts the type-checked AST into output files. The emitter orchestrates a pipeline of transformers, each handling a specific downlevel transformation:

  • TypeScript → JavaScript (strip types, transform enums)
  • ES2015+ → ES5 (arrow functions, classes, destructuring, generators, async/await)
  • JSX → JavaScript (createElement/jsx calls)
  • Module → target format (CommonJS, AMD, SystemJS, UMD, ESM)
  • Declaration emit (.d.ts generation)

Module Resolution

Module resolution (moduleNameResolver.ts) implements multiple strategies:

Strategy Algorithm
nodenext / node16 Node.js native ESM resolution with package.json exports/imports fields
bundler Relaxed ESM resolution (no extension required, exports supported)
node10 (formerly node) Legacy Node.js resolution (main field, index.js convention)
classic TypeScript's original resolution (deprecated)

Resolution steps (simplified):

  1. Check paths mappings
  2. Check rootDirs virtual directories
  3. Try file extensions: .ts, .tsx, .d.ts, .js, .jsx
  4. Check package.json exports/main/types/typings
  5. Check @types packages
  6. Check node_modules up the directory tree

Program and Project Management

The Program object (program.ts) represents a complete compilation unit:

  • Resolves the full set of source files from tsconfig.json
  • Creates and manages the SourceFile instances
  • Coordinates the checker and emitter
  • Handles incremental build state (.tsbuildinfo)
  • Manages project references and composite builds

The sys module (sys.ts) abstracts file system operations, enabling TypeScript to run in different environments (Node.js, browser, virtual file systems for testing).

Module Reference

src/compiler/types.ts

Defines the complete TypeScript AST type hierarchy. Contains:

  • SyntaxKind enum (all node types)
  • AST node interfaces (Node, Statement, Expression, Declaration, etc.)
  • Type system interfaces (Type, Symbol, Signature)
  • CompilerOptions interface
  • Diagnostic types
  • SourceFile interface

src/compiler/core.ts

Core utility functions used throughout the compiler:

  • Array manipulation (map, filter, flatMap, some, every)
  • Queue data structure
  • String utilities
  • Assertion helpers via Debug
  • Memoization utilities

src/compiler/commandLineParser.ts

Parses CLI arguments and tsconfig.json files:

  • parseCommandLine() — parse tsc arguments
  • parseJsonConfigFileContent() — parse tsconfig.json
  • convertCompilerOptionsFromJson() — JSON to CompilerOptions
  • generateTSConfig() — produce default tsconfig.json (for --init)
  • Contains the authoritative list of all compiler options with their types, defaults, categories, and descriptions

src/compiler/sys.ts

System abstraction layer:

  • File reading/writing
  • Directory operations
  • File watching (watchFile, watchDirectory)
  • Environment variable access
  • Process management
  • Supports multiple watch strategies (fs events, polling variants)

src/services/services.ts

The LanguageService interface and its implementation. Key methods:

Method Purpose
getCompletionsAtPosition() IntelliSense completions
getCompletionEntryDetails() Detailed completion info
getSemanticDiagnostics() Type errors
getSyntacticDiagnostics() Parse errors
getSuggestionDiagnostics() Suggestions (unused vars, etc.)
getDefinitionAtPosition() Go to definition
getReferencesAtPosition() Find all references
getRenameInfo() / findRenameLocations() Symbol rename
getSignatureHelpItems() Function signature help
getQuickInfoAtPosition() Hover information
getCodeFixesAtPosition() Quick fixes for diagnostics
getApplicableRefactors() Available refactorings
getEditsForRefactor() Apply a refactoring
getFormattingEditsForRange() Format code
organizeImports() Sort and remove unused imports
getOutliningSpans() Code folding regions
getDocumentHighlights() Symbol highlighting
getNavigationBarItems() Navigation bar structure
getNavigateToItems() Go to symbol search
getCallHierarchyIncomingCalls() Call hierarchy
provideInlayHints() Inlay hints (parameter names, return types)

src/services/formatting/

The formatting engine, documented in its own README:

  • Formatting decisions are rule-based (rules.ts contains the full rule set)
  • Rules specify spacing/indentation between pairs of AST nodes
  • The formatter is NOT publicly exported; it's only accessible through the language service
  • Used by all language service operations that insert or modify code

src/server/session.ts

The tsserver session handles the JSON protocol between editors and the language service:

  • Registers command handlers for all protocol commands
  • Maps protocol requests to language service API calls
  • Handles request cancellation
  • Manages asynchronous operations (semantic diagnostics, project loading)

src/server/project.ts

Defines project types:

Project Type Purpose
ConfiguredProject Backed by a tsconfig.json file
InferredProject Created for files not in any tsconfig.json
ExternalProject Created by external tools (e.g., IDEs with custom project models)
AutoImportProviderProject Virtual project for auto-import suggestions from node_modules

Code Patterns and Conventions

Pattern Convention
Module organization Barrel re-exports via _namespaces/ directories
Immutability AST nodes are read-only after creation; modifications via factory functions
Error handling Debug.assert() / Debug.fail() for invariants; diagnostics for user-facing errors
Internal marking /** @internal */ JSDoc tag for non-public API
Compilation model Self-hosted: TypeScript compiles itself; devDependencies includes typescript for bootstrapping
Build output built/local/ for development builds; lib/ for published output
Test baselines Expected output files in tests/baselines/reference/; "accept baselines" to update
Source targets Development builds target ES2020 with NodeNext modules
String interning Heavy use of __String branded type for interned identifier text

Testing Strategy

TypeScript uses a multi-layered testing approach:

1. Compiler baseline tests (src/testRunner/compilerRunner.ts)

  • Conformance tests (tests/cases/conformance/): ECMAScript spec conformance
  • Compiler tests (tests/cases/compiler/): regression tests for specific bugs
  • Each test is a .ts file; output is compared against reference baselines

2. Fourslash tests (src/harness/fourslashImpl.ts)

  • Language service integration tests
  • Use a special markup syntax with markers (/**/) and annotations
  • Test completions, go-to-definition, refactoring, code fixes, formatting
  • Each test file defines both the source code and expected behavior

3. Project tests

  • Test tsconfig.json parsing and resolution
  • Test project references and composite builds
  • Test build mode (--build) behavior

4. Unit tests (src/testRunner/unittests/)

  • Test individual components (config parsing, services, etc.)
  • Standard Mocha describe/it structure

5. Parallel test execution (src/testRunner/parallel/)

  • Worker-based parallel test runner
  • Distributes test files across multiple Node.js workers
  • Custom Mocha mixins for timeout and clone support

Note

The test suite contains 80,000+ files, with the vast majority being baseline reference files (expected outputs). The actual source code under src/ is approximately 250 files totaling ~7MB.

Potential Improvements

Based on source analysis and community issues:

  1. Module default behavior in v6: Community issue #63330 discusses that the default module setting in TypeScript 6.0 may not be esnext as expected. This transition area may need documentation updates.

  2. rewriteRelativeImportExtensions for declarations: Issue #61037 notes that tsc doesn't rewrite extensions in emitted declaration files even when rewriteRelativeImportExtensions is enabled. This is a known limitation.

  3. baseUrl deprecation discussion: Issue #62207 proposes deprecating baseUrl in favor of paths with relative resolution. This would affect many existing configurations.

  4. Language server stability: Issues #63405 and #63151 report recurring language server crashes, particularly on large projects. Memory management and complex type computation are contributing factors.

  5. Error message clarity: Issue #63206 reports confusing error messages (TS2322 vs TS2741) for certain property assignment scenarios. Error message quality is an ongoing area of improvement.

Contributing

Setup:

git clone https://github.com/microsoft/TypeScript.git
cd TypeScript
npm install
npm run setup-hooks
npm run build

Development workflow:

  1. Make changes in src/
  2. Build: npm run build:compiler
  3. Test: npm test
  4. Lint: npm run lint
  5. Format: npm run format

Running specific tests:

npx hereby runtests --tests=<test-name-regex>

Updating baselines after intentional changes:

npx hereby baseline-accept

Caution

Always review baseline changes carefully before accepting. Baseline diffs can reveal unintended behavioral changes that affect downstream users.

Key conventions for contributors:

  • All code is TypeScript (self-hosted)
  • Use Debug.assert() for invariants, not throw
  • Mark non-public API with /** @internal */
  • Add baseline tests for compiler changes, fourslash tests for language service changes
  • The codebase uses hereby (not Gulp) for build tasks
  • Formatting is enforced by dprint; run npm run format before committing
  • Custom ESLint rules in scripts/eslint/ enforce project-specific patterns

9. Integration Points

Editor Integration

TypeScript integrates with editors through tsserver, which communicates via a JSON-based protocol over stdin/stdout:

Editor Integration Method
VS Code Built-in TypeScript extension uses tsserver directly
Vim/Neovim Via LSP clients (nvim-lspconfig, coc.nvim)
Sublime Text LSP package with TypeScript configuration
JetBrains IDEs Built-in TypeScript support (uses own parser + tsserver for some features)
Emacs Via lsp-mode or eglot

Language Service Plugin API

Plugins extend the language service with custom behavior:

function init(modules: { typescript: typeof ts }): ts.server.PluginModule {
  return {
    create(info: ts.server.PluginCreateInfo) {
      const proxy = Object.create(null);
      for (const k of Object.keys(info.languageService)) {
        proxy[k] = (info.languageService as any)[k];
      }
      // Override methods as needed
      proxy.getCompletionsAtPosition = (fileName, position, options) => {
        const prior = info.languageService.getCompletionsAtPosition(fileName, position, options);
        // Modify completions...
        return prior;
      };
      return proxy;
    },
  };
}

export = init;

Configure in tsconfig.json:

{
  "compilerOptions": {
    "plugins": [
      { "name": "my-typescript-plugin" }
    ]
  }
}

Build Tool Integration

Tool Integration
esbuild --loader:.ts=ts (no type checking; use tsc --noEmit separately)
Vite Built-in TypeScript support via esbuild
webpack ts-loader or babel-loader with @babel/preset-typescript
Rollup @rollup/plugin-typescript
SWC @swc/core with TypeScript support (transpile-only)
Babel @babel/preset-typescript (transpile-only)

Note

Bundlers and transpilers like esbuild, SWC, and Babel perform transpilation only — they strip type annotations without checking them. Always run tsc --noEmit separately for type safety.

Programmatic API

Key entry points for embedding TypeScript:

import * as ts from "typescript";

// Create a program from files
const program = ts.createProgram(fileNames, compilerOptions);

// Parse a single file
const sourceFile = ts.createSourceFile(
  "example.ts",
  sourceCode,
  ts.ScriptTarget.Latest
);

// Create a language service
const service = ts.createLanguageService(host);

// Parse tsconfig.json
const config = ts.readConfigFile("tsconfig.json", ts.sys.readFile);
const parsed = ts.parseJsonConfigFileContent(config.config, ts.sys, ".");