typespec-rs
A Rust implementation of the TypeSpec type system — parser, type checker, and emitter.
What is TypeSpec?
TypeSpec is a language for describing cloud service APIs. It lets you define models, operations, and services declaratively, then generate OpenAPI, JSON Schema, protobuf, and other formats from a single source of truth.
typespec-rs is an independent Rust port of the TypeSpec compiler — not a binding to the TypeScript compiler. It implements the parser, checker, and emitter pipeline natively in Rust.
Note: This project is not affiliated with or endorsed by Microsoft. TypeSpec is a trademark of Microsoft Corporation.
Status
This project is in early development. The core compiler pipeline works:
| Component | Status |
|---|---|
| Scanner/Lexer | Complete |
| Parser | Complete |
| Type Checker | Partial |
| YAML Emitter | Working |
| JSON Emitter | Working |
| OpenAPI 3 Emitter | Working |
CLI (tspc) |
Working |
| WASM Extensions | Working |
| Programmatic Decorator API | Working |
2,800+ tests passing.
Quick Start
Library
Add to your Cargo.toml:
[]
= "0.2.0"
Parse TypeSpec and emit YAML/JSON:
use ;
let src = r#"
model Pet {
id: string;
name: string;
age?: int32;
type: "dog" | "cat" | "bird";
}
"#;
let yaml = to_yaml.unwrap;
println!;
let json = to_json.unwrap;
println!;
CLI
Install tspc:
Or download pre-built binaries from GitHub Releases.
Usage:
# Parse to JSON (default)
# Parse to YAML
# Generate OpenAPI 3.0
# OpenAPI 3.1
# Write to file
# Type-check only
# Read from stdin
|
Custom Decorators
typespec-rs provides two ways to register custom decorators:
Programmatic Registration (Recommended)
Register decorators directly on the Checker before calling check_program(). This bypasses source parsing, so it works with reserved keywords (flag, arg, env) and complex types without type resolution issues:
use Checker;
use parser;
let parse_result = parse;
let mut checker = new;
checker.set_parse_result;
// Register custom decorators
checker.register_decorator;
checker.register_decorator;
checker.register_decorator;
// Or batch registration
checker.register_decorators;
checker.check_program;
If the namespace doesn't exist yet, it will be created automatically under the global namespace. Duplicate registrations (same name + namespace) are silently skipped.
Library Source Injection
For decorators that need parameter type information, inject TypeSpec source via the library registry:
use ;
use http_library_source;
// Register at startup
register_library;
// parse() now automatically injects all registered libraries
let result = parse;
ParseOptions Presets
For one-off usage without global state:
use ;
// With HTTP library
let result = new.parse;
// With HTTP + custom libraries
let result = new.parse;
// Builder pattern
let result = new.parse;
WASM Extensions (Experimental)
tspc supports loading WASM extensions for custom decorators and output formats. Enable the wasm-extensions feature:
[]
= { = "0.2.0", = ["wasm-extensions"] }
# Load a WASM extension
WASM extensions can:
- Declare custom decorators (registered programmatically, avoiding keyword conflicts)
- Handle decorator invocation during type checking
- Read/write decorator state via
tsp.state_set/tsp.state_gethost functions - Report diagnostics back to the compiler
- Provide custom emitters for new output formats
WASM Extension ABI
A WASM extension must export the following functions:
| Export | Signature | Description |
|---|---|---|
allocate |
(i32) -> i32 |
Allocate n bytes in guest memory |
deallocate |
(i32, i32) |
Free guest memory |
tsp_ext_manifest |
() -> i32 |
Return pointer to JSON manifest |
tsp_ext_manifest_len |
() -> i32 |
Return manifest length |
tsp_ext_init |
(i32, i32) -> i32 |
Initialize with options JSON |
tsp_ext_handle_decorator |
(i32, i32) -> i32 |
Handle a decorator application |
tsp_ext_emit |
(i32, i32) -> i32 |
Emit output from type graph JSON |
tsp_ext_emit_len |
() -> i32 |
Return emit output length |
And can import host functions from the tsp namespace:
| Import | Signature | Description |
|---|---|---|
tsp.log |
(ptr, len) |
Log a message |
tsp.state_set |
(key_ptr, key_len, type_id, val_ptr, val_len) |
Set decorator state |
tsp.state_get |
(key_ptr, key_len, type_id) -> i32 |
Get state (returns length or -1) |
tsp.state_get_read |
(buf_ptr) |
Copy last state_get result to guest |
tsp.state_add |
(key_ptr, key_len, type_id) |
Add to state set |
tsp.state_has |
(key_ptr, key_len, type_id) -> i32 |
Check state (1/0) |
tsp.report_diagnostic |
(severity, code_ptr, code_len, msg_ptr, msg_len) |
Report diagnostic |
Manifest Format
The manifest JSON returned by tsp_ext_manifest:
Execution Flow
- Pre-parse: Extension manifests are extracted; decorators registered on the Checker
- Parse + Check: User source is parsed and type-checked (decorators resolved from registry)
- Decorator handling: For each type with a matching decorator,
tsp_ext_handle_decoratoris called with{ "type_id": N, "decorator_name": "...", "args": [...] } - Emit: If the extension handles the requested format,
tsp_ext_emitis called with the serialized type graph JSON
Examples
Run with cargo run --example <name>:
| Example | Description |
|---|---|
quick_start |
Convert TypeSpec to YAML/JSON in 5 lines |
model_examples |
Model definitions with optional fields, unions, arrays |
parse_and_inspect |
Low-level AST parsing and inspection |
petstore |
Full PetStore API parsing example |
tsp_to_json |
Parse and emit with JSON/YAML output |
Architecture
Source Code → Scanner → Parser → AST → Checker → Typed AST → Emitter → Output
- Scanner (
scanner/) — Tokenizes TypeSpec source intoTokenKindstream - Parser (
parser/) — Builds an AST from the token stream - Checker (
checker/) — Type checking, symbol resolution, decorator validation - Emitter (
emit/) — Converts checked types to YAML, JSON, or OpenAPI - CLI (
crates/tspc/) — Command-line interface with WASM extension support - Libs (
libs/) — Built-in library sources (HTTP, OpenAPI, etc.)
Feature Coverage
What's ported from the TypeSpec compiler:
- Full scanner with doc comments, string templates, conflict markers
- Complete parser for all declaration types
- Type system with 25+ type kinds (Model, Interface, Enum, Union, Scalar, Template, etc.)
- Type relation/assignability checking
- Decorator application and validation
- Template declaration and instantiation
- Standard library types (string, int32, float64, utcDateTime, etc.)
- Helper libraries: HTTP types, status codes, content types, URI templates, OpenAPI/OpenAPI3/JSON Schema/protobuf/versioning type definitions
- External library injection API for custom decorator declarations
- Programmatic decorator registration (
Checker::register_decorator) — bypasses source parsing, supports reserved keywords - WASM extension system with wasmtime runtime — custom decorators and emitters
- CLI with cross-platform binary releases (UPX compressed)
What's not yet ported:
- Full
Programpipeline (multi-file compilation, import resolution) - Decorator execution at
finishTypetime - HTTP route/payload resolution
- OpenAPI3 / JSON Schema emitter implementations
- Language Server Protocol (LSP) support
- Source loader (async I/O)
Development
# Run tests
# Run CLI tests
# Run linter
# Check formatting
# Build docs
# Run examples
Dependencies
| Crate | Purpose |
|---|---|
regex |
Pattern matching in scanner |
bitflags |
Bitflag types for visibility, symbol flags |
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
License
This project is licensed under the MIT License.
Security
See SECURITY.md for vulnerability reporting guidelines.