Skip to main content

The Type Checker

The type checker is the largest and most complex component of the TypeScript compiler. Located in src/compiler/checker.ts (over 3.1 MB), it performs semantic analysis and type validation.

Creating the Type Checker

The type checker uses var instead of let/const to avoid Temporal Dead Zone (TDZ) runtime checks, improving performance. See TypeScript Issue #52924.

Type Checker Responsibilities

The checker performs multiple critical functions:

Type Inference

Determines types of expressions without explicit annotations

Type Compatibility

Checks if one type can be assigned to another

Signature Resolution

Resolves overloaded function calls

Flow Analysis

Tracks type narrowing through control flow

How Type Checking Works

Step 1: Symbol Resolution

The checker first resolves all symbols created by the binder:

Step 2: Type Computation

Types are computed recursively from AST nodes:

Step 3: Compatibility Checking

The checker validates assignments using structural type comparison:

Type System Features

Structural Typing

TypeScript uses structural (duck) typing:
The checker determines compatibility by comparing the structure (shape) of types, not their names.

Union Types

The checker handles union types by ensuring operations are valid on all constituents:

Type Narrowing

Control flow analysis narrows types within conditional branches:

Generic Types

The checker performs type parameter substitution:

Type Checking Algorithm

1

Get Type of Source

Determine the type of the source expression
2

Get Type of Target

Determine the type of the target
3

Check Assignability

Verify source type is assignable to target type
4

Report Diagnostics

Generate errors for incompatible assignments

Diagnostic Generation

The checker creates detailed error messages:

Diagnostic Categories

Performance Optimizations

The type checker employs several optimization strategies:

Lazy Evaluation

Type checking is deferred until needed, avoiding work on unused code paths.

Type Caching

Types are computed once and cached:

Signature Caching

Resolved function signatures are cached to avoid recomputation:

Internal Type Representations

Type Flags

Type Hierarchy

Advanced Features

The checker evaluates conditional types by checking constraints:
The checker transforms types by mapping over properties:
The checker manipulates string literal types:
The checker tracks covariance and contravariance:

Compiler Overview

Learn about the full compilation pipeline

Module Resolution

Understand how imports are resolved