structural-typing 0.1.3

Type-level field presence tracking for Rust structs, inspired by TypeScript
Documentation

Structural Typing for Rust

Define a struct once and use it with different field combinations, tracked at compile time. Inspired by TypeScript, RDF, and this talk.

Status: Experimental. API subject to change.

Installation

cargo add structural-typing

If you use derives on your #[structural] structs, also add:

cargo add derive-where

Example

use structural_typing::{structural, presence::Present, select};

#[structural]
struct User {
    id: u32,
    name: String,
    email: String,
}

type Create = select!(user: name, email);

fn create_user(data: User<Create>) -> User {
    data.id(generate_id())
}

fn update_user<F: user::Fields<id = Present>>(data: User<F>) {
    if let Some(name) = data.get_name() {
        update_in_db(data.id, name);
    }
}

fn main() {
    let new_user = User::empty()
        .name("Alice".to_owned())
        .email("alice@example.com".to_owned());

    let user = create_user(new_user);

    let partial = User::empty().id(user.id).name(Some("Bob".to_owned()));
    update_user(partial);
}

fn generate_id() -> u32 { 42 }
fn update_in_db(id: u32, name: &String) { /* ... */ }

See examples/ for comprehensive usage including merge, split, serde integration, and more.

Features

  • Compile-time field requirements
  • Builder API with type inference
  • Merge and split operations
  • Serde support (via serde feature)
  • Zero runtime overhead

Constraints

  • Named structs only (not tuple structs or enums)
  • No generic parameters
  • At least one field required

License

MIT OR Apache-2.0