Can typescript-go Generate Union Types from Go? A Technical Deep Dive
No, typescript-go cannot generate TypeScript union types from Go source code because it is a TypeScript compiler implementation written in Go, not a source-to-source transpiler that converts Go into TypeScript.
The typescript-go repository represents Microsoft's experimental effort to reimplement the TypeScript compiler in Go for improved performance. Despite being implemented in Go, this compiler exclusively parses TypeScript (.ts and .tsx) files and emits JavaScript or declaration files, meaning it possesses no capability to inspect Go structs or interfaces and generate corresponding TypeScript union types.
Understanding the Compiler's Architecture
The typescript-go project serves as a complete reimplementation of the TypeScript language services. It performs lexical analysis, syntactic parsing, type checking, and code emission—functionally mirroring the original TypeScript compiler but with Go's runtime characteristics.
The compiler builds an Abstract Syntax Tree (AST) from TypeScript source code, where union types are represented internally as UnionTypeNode structures. These nodes are defined in internal/ast/ast_generated.go at lines 5299-5315, containing the constituent types joined by the | operator.
How Union Types Are Processed Internally
When working with TypeScript source files, the compiler handles union types through three distinct phases: parsing, AST representation, and code emission.
Parsing Union Syntax
When the parser encounters the | token within a type annotation, it invokes the parseUnionOrIntersectionType function in internal/parser/parser.go (lines 2631-2665). This function constructs a UnionTypeNode by collecting individual type constituents and validating their positions within the type hierarchy.
AST Representation and Validation
The internal structure resides in internal/ast/ast_generated.go, where the UnionTypeNode struct stores references to constituent types. Helper predicates like IsUnionTypeNode enable the type checker and transformers to identify these nodes during tree traversal and semantic analysis.
Code Emission and Printing
During the emission phase, internal/printer/printer.go (lines 2010-2020) implements emitUnionType and emitUnionTypeConstituent to regenerate the a | b syntax. Additionally, the declaration transformer in internal/transformers/declarations/transform.go (lines 2006-2027) constructs UnionTypeNode instances when generating declaration files from existing TypeScript sources.
Why Go Source Code Cannot Generate Union Types
Although typescript-go is implemented in Go, the codebase contains no components that parse Go files or translate Go constructs into TypeScript AST nodes. The CLI entry point at cmd/tsgo/main.go explicitly restricts input to TypeScript extensions, and the parser immediately fails on Go syntax.
Consider this Go struct definition:
// file: shapes.go
type Shape struct {
Kind string // "circle" or "square"
Radius float64
Side float64
}
There is no function within the repository that walks Go AST nodes and produces a UnionTypeNode. The constructors for union types exclusively accept TypeScript AST nodes as parameters, confirming the compiler processes only TypeScript-to-JavaScript transformation, not Go-to-TypeScript transpilation.
Working with Union Types in typescript-go
To utilize union types, you must author TypeScript code directly. The compiler fully supports union syntax written in TypeScript:
// file: shapes.ts
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
if (s.kind === "circle") return Math.PI * s.radius ** 2;
return s.side ** 2;
}
Compiling with the typescript-go CLI:
npx tsgo shapes.ts
The compiler parses the | tokens, creates the UnionTypeNode in its AST, performs type narrowing analysis, and emits the corresponding JavaScript. For decorator metadata, the compiler additionally handles union type serialization through serializeUnionOrIntersectionConstituents in internal/transformers/tstransforms/typeserializer.go.
Summary
- typescript-go is a TypeScript compiler written in Go, not a transpiler from Go to TypeScript.
- The compiler constructs UnionTypeNode instances defined in
internal/ast/ast_generated.goexclusively from TypeScript source input. - Parsing occurs via
parseUnionOrIntersectionTypeininternal/parser/parser.go, while emission usesemitUnionTypeininternal/printer/printer.go. - The
tsgoCLI only accepts.tsand.tsxfiles, rejecting Go source files entirely. - Union types must be authored manually in TypeScript or generated by separate tooling, then fed to typescript-go for compilation.
Frequently Asked Questions
Is typescript-go a transpiler that converts Go code to TypeScript?
No. typescript-go is a TypeScript compiler implementation that parses TypeScript and emits JavaScript. While the compiler itself is written in Go, it does not understand Go syntax or transpile Go constructs into TypeScript definitions.
What file extensions does typescript-go accept?
The compiler only processes files with .ts or .tsx extensions. According to the CLI implementation in cmd/tsgo/main.go, attempting to compile Go files or other languages results in parsing errors because the lexical analyzer only recognizes TypeScript grammar tokens.
How are union types represented in the typescript-go AST?
Union types use the UnionTypeNode struct defined in internal/ast/ast_generated.go (lines 5299-5315). The parser instantiates these nodes via parseUnionOrIntersectionType in internal/parser/parser.go when encountering the | operator, and the printer emits them through emitUnionType in internal/printer/printer.go.
Can I automatically generate TypeScript union types from Go structs using this tool?
No. The repository contains no logic to inspect Go-specific constructs like structs or interfaces. To generate TypeScript definitions containing unions from Go code, you must use a separate code generation tool or write the TypeScript interfaces manually before compilation.
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 →