tauri-ts-generator 1.3.0

CLI tool to generate TypeScript bindings from Tauri commands
Documentation

tauri-ts-generator

A powerful CLI tool to automatically generate TypeScript bindings from your Rust Tauri commands, structs, and enums.

tauri-ts-generator scans your Rust source code, parses #[tauri::command] macros and data structures, and generates type-safe TypeScript interfaces and invocation functions. This eliminates manual typing boilerplate and ensures your frontend and backend are always in sync.

Features

  • Automated Scanning: Recursively scans your src-tauri directory for commands and types.
  • Type Safety: Generates exact TypeScript definitions for Rust structs, enums, and type aliases.
  • Serde Support:
    • Respects #[serde(rename = "...")] attributes, preserving the exact name and overriding camelCase conversion.
    • Handles #[serde(rename_all = "...")] for enums.
    • Supports #[serde(tag = "...")], #[serde(content = "...")], and #[serde(untagged)] enum representations.
  • Smart Type Mapping:
    • Maps common Rust types (String, Vec, Option, Result) to TypeScript equivalents.
    • Handles external crate types like chrono::DateTime, uuid::Uuid, url::Url, and rust_decimal::Decimal.
  • Async Handling: Correctly generates Promise<T> for async commands.
  • Tauri Integration:
    • Automatically imports invoke from @tauri-apps/api/core.
    • Supports #[tauri::command(rename_all = "...")] to control argument casing (e.g. snake_case).
  • Macro Support: Optional integration with cargo-expand to resolve types generated by macros (e.g., progenitor).
  • Conflict Resolution: Detects and handles naming conflicts or ambiguous imports.

Installation

cargo install tauri-ts-generator

Or run directly from source:

cargo run --release -- generate

Quick Start

  1. Initialize Configuration (Run in your Tauri project root):

    tauri-ts-generator init
    

    This creates a tauri-codegen.toml file.

  2. Generate Bindings:

    tauri-ts-generator generate
    

Configuration (tauri-codegen.toml)

Customize the generator behavior using the TOML configuration file.

[input] Section

Defines where the generator looks for code.

Key Description Default
source_dir Root directory of your Rust source code. "src-tauri/src"
exclude List of directories or files to ignore. ["tests", "target"]
use_cargo_expand Enable if you use macro-generated types (requires cargo-expand). false
cargo_manifest Path to Cargo.toml for cargo-expand. Auto-detected if empty. None

[output] Section

Defines where the generated TypeScript files are saved.

Key Description Default
types_file Path for generated interfaces/types. "src/generated/types.ts"
commands_file Path for generated invoke functions. "src/generated/commands.ts"

[naming] Section

Customize naming conventions for generated types and functions.

Key Description Default
type_prefix Prefix added to all generated interface names (e.g., "I"). ""
type_suffix Suffix added to all generated interface names (e.g., "DTO"). ""
function_prefix Prefix for generated command functions. ""
function_suffix Suffix for generated command functions. ""

Type Mappings

The generator maps Rust types to TypeScript as follows:

Rust Type TypeScript Type
String, &str, char string
i8...i64, u8...u64, f32, f64 number
bool boolean
Option<T> T | null
Vec<T> T[]
HashMap<K, V> Record<K, V> (if K is string/number)
Result<T, E> Promise<T> (in return types)
() / Unit void
bytes::Bytes number[]
serde_json::Value unknown

Supported External Types

Common types from popular crates are mapped automatically:

  • Chrono: DateTime, NaiveDate, NaiveTimestring
  • Time: OffsetDateTime, Datestring
  • Uuid: Uuidstring
  • Url: Urlstring
  • Rust Decimal: Decimalstring
  • Std: Path, PathBuf, IpAddrstring; Durationnumber

Examples

1. Basic Command & Struct

Rust:

#[derive(Serialize)]
pub struct User {
    pub id: i32,
    pub name: String,
}

#[tauri::command]
pub async fn get_user(id: i32) -> Result<User, String> { /* ... */ }

TypeScript Output:

export interface User {
  id: number;
  name: string;
}

export async function getUser(id: number): Promise<User> {
  return invoke<User>("get_user", { id });
}

2. Serde Rename (Exact Casing)

When #[serde(rename = "...")] is used, the generator preserves the exact casing, skipping the default camelCase conversion.

Rust:

#[derive(Serialize)]
pub struct Config {
    #[serde(rename = "API_KEY")]
    pub api_key: String,
    pub retries: i32,
}

TypeScript Output:

export interface Config {
  API_KEY: string;  // Exactly as renamed in Rust
  retries: number;  // Default camelCase
}

3. Enums

Supports various serde representations.

Rust:

#[derive(Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum Status {
    Active,
    Inactive,
}

TypeScript Output:

export type Status = "ACTIVE" | "INACTIVE";

4. Command Arguments Rename

Use rename_all on commands to control argument keys in the invoke payload.

Rust:

#[tauri::command(rename_all = "snake_case")]
pub fn update_user(user_id: i32, new_email: String) { /* ... */ }

TypeScript Output:

export async function updateUser(userId: number, newEmail: string): Promise<void> {
  // Arguments are mapped to snake_case in the payload
  return invoke<void>("update_user", { user_id: userId, new_email: newEmail });
}

CLI Reference

tauri-ts-generator <COMMAND> [OPTIONS]

Commands:
  generate    Generate TypeScript bindings
  init        Create a default configuration file
  help        Print help information

Options:
  -v, --verbose   Enable verbose logging (useful for debugging scanning/parsing)
  -c, --config    Path to config file (default: tauri-codegen.toml)

License

MIT