tauri-ts-generator 1.2.0

CLI tool to generate TypeScript bindings from Tauri commands
Documentation

tauri-ts-generator

CLI tool to automatically generate TypeScript bindings from Tauri commands.

Description

tauri-ts-generator scans your Rust code, finds all functions with the #[tauri::command] macro, and automatically generates:

  • TypeScript interfaces for Rust structs and enums
  • TypeScript wrapper functions to invoke Tauri commands via invoke()

This ensures type-safe interaction between the TypeScript frontend and Rust backend, minimizing manual boilerplate.

Installation

cargo install --path .

Or build from source:

cargo build --release

Quick Start

1. Initialize Configuration

cd your-tauri-project
tauri-ts-generator init

This will create a tauri-codegen.toml file with default settings.

2. Configure Settings

Edit tauri-codegen.toml:

[input]
source_dir = "src-tauri/src"
exclude = ["tests", "target"]
# Optional: enable for macro-generated types (requires cargo-expand)
# use_cargo_expand = true
# cargo_manifest = "src-tauri/Cargo.toml"

[output]
types_file = "src/generated/types.ts"
commands_file = "src/generated/commands.ts"

[naming]
type_prefix = ""
type_suffix = ""
function_prefix = ""
function_suffix = ""

3. Generate TypeScript Code

tauri-ts-generator generate

Or with verbose output:

tauri-ts-generator generate --verbose

Example

Rust Code (Input)

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct User {
    pub id: i32,
    pub name: String,
    pub email: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub enum UserStatus {
    Active,
    Inactive,
    Pending,
}

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

#[tauri::command]
pub async fn get_all_users() -> Result<Vec<User>, String> {
    // ...
}

#[tauri::command]
pub fn greet(name: String) -> String {
    format!("Hello, {}!", name)
}

TypeScript Code (Output)

types.ts:

// This file was auto-generated by tauri-ts-generator
// Do not edit this file manually

export interface User {
  id: number;
  name: string;
  email: string | null;
}

export type UserStatus = "Active" | "Inactive" | "Pending";

commands.ts:

// This file was auto-generated by tauri-ts-generator
// Do not edit this file manually

import { invoke } from "@tauri-apps/api/core";
import type { User } from "./types";

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

export async function getAllUsers(): Promise<User[]> {
  return invoke<User[]>("get_all_users");
}

export async function greet(name: string): Promise<string> {
  return invoke<string>("greet", { name });
}

Type Mapping

Basic Types

Rust TypeScript
String, &str, char string
i8, i16, i32, i64, u8, u16, u32, u64 number
f32, f64 number
bool boolean
Vec<T> T[]
Option<T> T | null
Result<T, E> Promise<T>
HashMap<K, V> Record<K, V>
() void
Custom struct TypeScript interface
Simple enum String union type

External Types (Crates)

Rust TypeScript Description
chrono::DateTime<Tz> string ISO 8601 format
chrono::NaiveDateTime string ISO 8601 format
chrono::NaiveDate string YYYY-MM-DD
chrono::NaiveTime string HH:MM:SS
time::OffsetDateTime string ISO 8601 format
time::PrimitiveDateTime string ISO 8601 format
uuid::Uuid string UUID string
rust_decimal::Decimal string Numeric string
std::path::PathBuf string File path
url::Url string URL string
std::net::IpAddr string IP address
std::time::Duration number Seconds
serde_json::Value unknown Any JSON
bytes::Bytes number[] Byte array
Complex enum Discriminated union

Configuration

[input]

Parameter Description Default
source_dir Directory with Rust source files src-tauri/src
exclude List of directories/files to exclude ["tests", "target"]
use_cargo_expand Use cargo expand for macro-generated types false
cargo_manifest Path to Cargo.toml for cargo expand auto-detected

[output]

Parameter Description Default
types_file Path to generate TypeScript types src/generated/types.ts
commands_file Path to generate TypeScript commands src/generated/commands.ts

[naming]

Parameter Description Default
type_prefix Prefix for type names ""
type_suffix Suffix for type names ""
function_prefix Prefix for function names ""
function_suffix Suffix for function names ""

CLI Commands

tauri-ts-generator <COMMAND>

Commands:
  generate  Generate TypeScript bindings
  init      Create configuration file
  help      Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

generate

tauri-ts-generator generate [OPTIONS]

Options:
  -c, --config <FILE>  Path to config file [default: tauri-codegen.toml]
  -v, --verbose        Verbose output
  -h, --help           Print help

init

tauri-ts-generator init [OPTIONS]

Options:
  -o, --output <FILE>  Path to create config file [default: tauri-codegen.toml]
  -f, --force          Overwrite existing file
  -h, --help           Print help

Features

  • Automated Parsing — uses syn to analyze Rust AST
  • Async Support — correctly handles async commands
  • Custom Types — parses structs and enums with #[derive(Serialize)] attributes
  • Serde Rename — respects #[serde(rename = "...")]
  • Tauri Special Types — automatically skips State, Window, AppHandle
  • Nested Modules — scans commands inside mod blocks
  • Wildcard Re-exports — supports pub use module::* patterns
  • Macro-generated Types — optional support via cargo expand

Macro-Generated Types

Some types in your project may be generated by macros (e.g., progenitor, derive_builder, etc.). These types don't exist as plain Rust source code, so the generator cannot find them by default.

Detecting Unresolved Types

When the generator encounters types it cannot resolve, it will show a warning:

Warning: 4 type(s) could not be resolved and will not be generated:
  - 'AuthTokens' (used in src/commands/auth.rs)
  - 'UserProfile' (used in src/commands/auth.rs)

Hint: These types may be generated by macros (e.g., progenitor, serde, etc.).
      To include macro-generated types, add to your config:
        [input]
        use_cargo_expand = true

Using cargo expand

To include macro-generated types, enable cargo expand in your configuration:

[input]
source_dir = "src-tauri/src"
use_cargo_expand = true
cargo_manifest = "src-tauri/Cargo.toml"  # optional, auto-detected

Requirements:

  • Install cargo-expand: cargo install cargo-expand
  • Nightly Rust toolchain (for cargo expand)

Note: Using cargo expand will compile your project, which may take longer than regular parsing.

License

MIT