Understanding typescript-go Core Functionalities: Architecture and Implementation
typescript-go is a native Go implementation of the TypeScript compiler that provides command-line compilation, JSON-RPC API services, LSP server capabilities, and incremental build systems through a modular architecture designed for high performance.
typescript-go reproduces the essential toolchain features of the official TypeScript compiler (tsc) while exposing them as a Go library and standalone processes. This repository, microsoft/typescript-go, organizes its core functionalities around distinct subsystems that handle everything from parsing source code to providing editor intelligence via the Language Server Protocol.
Command-Line Compiler (tsgo)
The command-line compiler serves as the primary entry point for users migrating from the Node.js-based TypeScript compiler. Located in cmd/tsgo/main.go, the CLI parses arguments, loads tsconfig.json configurations, and executes the full compilation pipeline.
The implementation delegates to internal/execute/tsc.go, which acts as the driver selecting between normal compilation and build modes. This module supports --watch for file monitoring, --build for project references, and --init for configuration scaffolding. Help text and option rendering are handled in internal/execute/tsc/help.go, ensuring parity with standard TypeScript CLI behavior.
API Server (JSON-RPC)
typescript-go exposes compiler functionality programmatically through a JSON-RPC/MessagePack API server. This subsystem allows external processes to invoke the compiler without spawning new CLI instances for each operation.
The server bootstrap logic resides in cmd/tsgo/api.go, while internal/api/server.go contains the core request handling implementation. The API supports communication over stdin/stdout or named pipes, making it suitable for integration with build systems and custom tooling. Runtime initialization accepts a StdioServerOptions struct to configure working directories, error logging, and default library paths.
Language Server Protocol (LSP) Implementation
Editor integrations rely on the LSP server, which provides IntelliSense features including completion, diagnostics, go-to-definition, and hover information. Process startup occurs in cmd/tsgo/lsp.go, with request routing and session management implemented in internal/lsp/server.go.
This subsystem shares the same parser and type checker as the batch compiler, ensuring consistent diagnostic output across CLI and editor environments. The LSP implementation leverages the virtual file system abstraction to handle unsaved file contents and rapid incremental updates typical in IDE workflows.
Core Compilation Pipeline
The heart of typescript-go consists of three interconnected stages that transform TypeScript source into executable JavaScript.
Parser and AST Generation
The Parser converts TypeScript source text into an Abstract Syntax Tree (AST) using algorithms defined in internal/parser/parser.go. Supporting utilities in internal/parser/utilities.go handle trivia management and node creation. This implementation maintains syntax compatibility with TypeScript 6.0, producing identical AST structures for equivalent source code.
Type Checker
Type resolution and checking occur in internal/checker/checker.go, which serves as the main type-checking engine. This module performs symbol resolution, control flow analysis, and type relationship validation. All compiler diagnostics and error messages originate here, feeding into the centralized diagnostics system for localization and formatting.
Emitter
The Emitter translates validated AST nodes into JavaScript output and optional declaration files (.d.ts). Implemented in internal/compiler/emitter.go, this stage handles source map generation, JSX transformation, and module format conversion (CommonJS, ES modules, etc.). The emitter respects compiler options regarding target ECMAScript version and output directory structures.
Incremental Build System
typescript-go implements sophisticated incremental compilation to minimize rebuild times in large codebases. The system tracks file hashes and dependency graphs through .tsbuildinfo files, managed primarily in internal/execute/incremental/program.go.
Project reference parsing, crucial for monorepo architectures, is handled by internal/compiler/projectreferenceparser.go. This subsystem determines build ordering between dependent projects and skip unchanged compilation units when inputs remain stable.
Virtual File System and File Watching
A Virtual File System (VFS) abstraction layer enables typescript-go to operate across diverse environments. The implementation in internal/vfs/osvfs.go wraps native OS operations, while internal/vfs/vfswatch/watcher.go provides file watching capabilities for --watch mode.
The VFS supports in-memory file systems for testing and read-only bundled libraries, ensuring the compiler functions without traditional node_modules installations. Watch notifications trigger selective recompilation, avoiding full project rebuilds when only specific files change.
Practical Usage Examples
Running CLI Compilation
Compile a project using the standard configuration file:
# Compile using tsconfig.json
npx tsgo
# Compile a single file directly
npx tsgo hello.ts
# Enable incremental watch mode
npx tsgo --watch --incremental
This invokes the entry point in cmd/tsgo/main.go, which instantiates the system implementation and executes the compilation pipeline defined in internal/execute/tsc.go.
Starting the API Server
Integrate the compiler into Go applications using the JSON-RPC server:
package main
import (
"context"
"log"
"github.com/microsoft/typescript-go/internal/api"
"github.com/microsoft/typescript-go/internal/bundled"
)
func main() {
opts := &api.StdioServerOptions{
Err: log.Writer(),
Cwd: ".",
DefaultLibraryPath: bundled.LibPath(),
}
srv := api.NewStdioServer(opts)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
if err := srv.Run(ctx); err != nil {
log.Fatalf("API server failed: %v", err)
}
}
This creates a StdioServer that listens for compilation requests and utilizes the bundled standard library definitions via bundled.LibPath().
Summary
- typescript-go is Microsoft's native Go port of the TypeScript compiler, offering CLI, API, and LSP server modes.
- The architecture separates concerns into distinct subsystems: parsing (
internal/parser/parser.go), type checking (internal/checker/checker.go), and emission (internal/compiler/emitter.go). - Incremental builds are supported through file hashing and
.tsbuildinfotracking ininternal/execute/incremental/program.go. - A virtual file system abstraction enables cross-platform operation and efficient file watching via
internal/vfs/vfswatch/watcher.go. - The JSON-RPC API (
internal/api/server.go) and LSP implementation (internal/lsp/server.go) provide programmatic access for tooling and editor integration.
Frequently Asked Questions
What is the difference between typescript-go and the standard TypeScript compiler?
typescript-go is a complete reimplementation of the TypeScript compiler toolchain written in Go rather than TypeScript/JavaScript. While it maintains compatibility with tsconfig.json options and TypeScript language features, it runs as a native binary without Node.js dependencies, offering potentially faster startup times and different memory characteristics. The core type-checking logic in internal/checker/checker.go produces the same diagnostics as the original compiler.
Can typescript-go be used as a drop-in replacement for tsc?
Yes, for supported features. The tsgo CLI accepts the same command-line arguments as tsc, including --watch, --build, and --strict flags. However, certain advanced features and third-party compiler plugins may not yet be implemented, as indicated by the project's feature matrix. The entry point at cmd/tsgo/main.go is designed to mimic tsc behavior closely.
How does the file watching system work in typescript-go?
The file watcher in internal/vfs/vfswatch/watcher.go monitors file system changes using OS-specific APIs and triggers incremental recompilation when source files change. When combined with --incremental mode, the system reads existing .tsbuildinfo files to determine which files require re-checking, significantly reducing compilation time for large projects during development.
Is the LSP server compatible with all editors?
The LSP implementation in internal/lsp/server.go follows the Language Server Protocol specification, making it compatible with any editor supporting LSP, including VS Code, Neovim, and Emacs. The server uses the same parser and checker instances as the batch compiler, ensuring that type errors shown in editors match those produced by command-line builds.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →