omitty 0.1.0

TypeScript-like Omit<> for Rust structs - no boilerplate
Documentation

omitty

A Rust procedural macro for generating type variants with omitted fields.

Features

  • Simple syntax - Generate variants with just #[omit_variant(VariantName, field1, field2)]
  • Automatic derive - Automatically generates Debug, Clone, Serialize, Deserialize, PartialEq, Eq
  • Serde compatible - Works seamlessly with serde for JSON/serialization
  • Type-safe - Compile-time guarantees for omitted fields

Installation

Add this to your Cargo.toml:

[dependencies]

omitty = "0.1.0"

serde = { version = "1.0", features = ["derive"] }

serde_json = "1.0"

Usage

Basic Example

use omitty::OmittableType;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, OmittableType)]
#[omit_variant(UserPublic, secret_token)]
pub struct User {
    pub id: String,
    pub username: String,
    pub secret_token: String,
}

This generates a new UserPublic struct with only id and username:

pub struct UserPublic {
    pub id: String,
    pub username: String,
}

Multiple Omitted Fields

use omitty::OmittableType;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, OmittableType)]
#[omit_variant(UserPublic, secret_token, password, internal_id, email)]
pub struct User {
    pub id: String,
    pub username: String,
    pub secret_token: String,
    pub password: String,
    pub internal_id: i64,
    pub email: String,
}

Multiple Variants

use omitty::OmittableType;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, OmittableType)]
#[omit_variant(UserPublic, secret_token, password, email)]
#[omit_variant(UserMinimal, secret_token, password, email, bio, avatar_url)]
pub struct User {
    pub id: String,
    pub username: String,
    pub secret_token: String,
    pub password: String,
    pub email: String,
    pub bio: String,
    pub avatar_url: String,
}

This generates both UserPublic and UserMinimal structs with different fields omitted.

Real-World Example: Discord-like API

use omitty::OmittableType;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, OmittableType)]
#[omit_variant(UserPublic, secret_token)]
pub struct User {
    pub id: String,
    pub username: String,
    pub secret_token: String,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Member {
    pub user: UserPublic,
    pub nick: String,
}

fn main() {
    let json = r#"{
        "user": {
            "id": "123",
            "username": "meetzli"
        },
        "nick": "Meetz"
    }"#;

    let member: Member = serde_json::from_str(json).unwrap();
    println!("Username: {}", member.user.username);
    println!("Nick: {}", member.nick);
}

Syntax

#[omit_variant(VariantName, field1, field2, field3, ...)]
  • VariantName: The name of the generated struct (identifier, not a string)
  • field1, field2, ...: Names of fields to omit from the original struct

Generated Derives

All generated variants automatically derive:

  • Debug
  • Clone
  • serde::Serialize
  • serde::Deserialize
  • PartialEq
  • Eq

Use Cases

  • API responses - Return public user data without sensitive fields
  • Database models - Create DTO variants without internal fields
  • Multi-tier data access - Different permission levels see different fields
  • Caching - Store lightweight versions of structs
  • Testing - Create test fixtures with subset of data

Error Messages

The macro provides clear, actionable error messages:

// Error: Omittable can only be derived for structs with named fields (not tuple structs or unit structs)
// Error: field type must be a path type (e.g., User, MyType). Complex types like references, arrays, or tuples are not supported
// Error: missing variant name as first argument in omit_variant attribute. Usage: #[omit_variant(VariantName, field1, field2, ...)]

License

MIT OR Apache-2.0