ts-rs
Generate TypeScript type bindings directly from your Rust types via a derive macro
Repository Health
Technical Analysis
ts-rs is a Rust crate that generates matching TypeScript type definitions straight from your Rust structs and enums using a #[derive(TS)] procedural macro, so a Rust backend and a TypeScript frontend can share one source of truth for their data shapes instead of maintaining hand-written, drift-prone .d.ts files. It understands serde attributes (rename, rename_all, skip, tag, flatten, etc.) out of the box, so types already annotated for JSON serialization typically need no extra work to also export correct TypeScript.
Beyond the basic derive, ts-rs supports generics, tuple structs, enums (including serde’s internally/externally/adjacently tagged and untagged representations), and optional integrations for common external types (chrono, uuid, bigdecimal, bytes, url, indexmap, semver, tokio, jiff, and more) behind Cargo feature flags, plus a format feature that runs generated output through a TypeScript formatter.
What You Get
- A
#[derive(TS)]procedural macro that generates a matching TypeScriptinterface/typefor any annotated Rust struct or enum - Automatic recognition of
serdeattributes (rename,rename_all,skip,tag,flatten, tagged/untagged enum representations) so serialization and TypeScript-export stay consistent - Feature-gated bindings for common external crates —
chrono,uuid,bigdecimal,bytes,url,indexmap,ordered-float,semver,tokio,jiff,arrayvec,smol_str,heapless,bson— so third-party types export sensible TypeScript equivalents - An
export()mechanism (andexport_to) for writing generated.tsfiles to disk, plus an optionalformatfeature that runs output throughdprint-plugin-typescriptfor consistent formatting - Support for generics, tuple structs, and all of serde’s enum representations (internally/externally/adjacently tagged, untagged)
Common Use Cases
- Keeping a Rust backend’s API request/response types in sync with a TypeScript frontend without maintaining hand-written
.d.tsfiles - Generating TypeScript types for a Tauri or WASM-frontend application built on shared Rust domain types
- Exporting TypeScript types for a Rust microservice’s message/event payloads consumed by a Node.js or browser client
- Enforcing compile-time type safety across a full-stack Rust+TypeScript project’s serialization boundary
Under The Hood
Architecture — The repository is a Cargo workspace of three crates: macros (the #[derive(TS)] proc-macro implementation, parsing struct/enum ASTs and serde attributes to generate a TS trait implementation), ts-rs (the runtime crate defining the TS trait, the export/export_to machinery under src/export/, and per-external-type binding modules like chrono.rs, tokio.rs, serde_json.rs, jiff.rs), and example (a workspace member demonstrating usage patterns), with e2e housing end-to-end conformance tests that assert generated TypeScript matches expectations.
Tech Stack — Pure Rust, built on syn/quote/proc-macro2 for the derive macro (standard Rust proc-macro tooling), with an extensive matrix of Cargo.toml feature flags (chrono-impl, uuid-impl, tokio-impl, jiff-impl, etc.) gating optional dependencies so consumers only compile bindings for external types they actually use. The optional format feature depends on dprint-plugin-typescript for output formatting.
Code Quality — The e2e directory of end-to-end tests checking exact generated-TypeScript output is a strong quality signal for a code-generation crate, where subtle formatting or type-mapping regressions are otherwise easy to miss in unit tests alone. A maintained CHANGELOG.md and CONTRIBUTING.md indicate an established contribution process; the per-external-crate integration modules (one file per supported type, e.g. chrono.rs, jiff.rs) keep each integration’s mapping logic isolated and independently testable.
API Design — The core workflow is a single #[derive(TS)] attribute reusing serde’s existing attribute vocabulary, so teams that already annotate their types for serde::Serialize/Deserialize get TypeScript export with near-zero additional annotation burden — a deliberate design choice that minimizes the learning curve for the crate’s primary audience (Rust teams already using serde for their API layer).
Used by 2 apps in this directory
cmux
Developer Tools · AI Development
A native, Ghostty-based macOS terminal with vertical tabs, agent-aware notifications, and a scriptable browser built for running many parallel AI coding agent sessions instead of juggling tmux panes.
Epicenter
Knowledge Management · Note Taking · Developer Tools
A local-first monorepo led by Whispering, an open-source speech-to-text app, built on an MIT toolkit that turns your data into plain Markdown and SQLite files you own instead of a database you rent.