#proc-macro #type #utility #macro #partial #typescript #omit

macro utility-types

This crate use proc-macro to realize several utility types of TypeScript

4 releases

0.0.4 Jul 30, 2024
0.0.3 Jun 16, 2024
0.0.2 Nov 26, 2021
0.0.1 Nov 26, 2021

#876 in Procedural macros

Download history 615/week @ 2024-07-25 638/week @ 2024-08-01 630/week @ 2024-08-08 857/week @ 2024-08-15 665/week @ 2024-08-22 828/week @ 2024-08-29 690/week @ 2024-09-05 675/week @ 2024-09-12 590/week @ 2024-09-19 886/week @ 2024-09-26 641/week @ 2024-10-03 183/week @ 2024-10-10 78/week @ 2024-10-17 18/week @ 2024-10-24 61/week @ 2024-10-31 46/week @ 2024-11-07

258 downloads per month
Used in bgmtv

MIT license

46KB
828 lines

utility types

This crate use proc-macro to realize several utility types of Typescript in Rust.

macro Typescript Utility Type
[Partial] Partial<Type>
[Pick] Pick<Type, Keys>
[Omit] Omit<Type, Keys>
[Extract] Extract<Type, Union>
[Exclude] Exclude<UnionType, ExcludedMembers>

Example

Here is an example of how to use this crate.

use utility_types::{Omit, Partial, Pick, Required};
#[derive(Clone, Partial, Required, Pick, Omit)]
#[partial(ident = PartialFoo, derive(Debug, PartialEq), forward_attrs())]
#[required(ident = RequiredFoo, derive(Debug, PartialEq), forward_attrs())]
#[pick(arg(ident = PickAB, fields(a, b), derive(Debug, PartialEq)), forward_attrs())]
#[omit(arg(ident = OmitCD, fields(c, d), derive(Debug, PartialEq)), forward_attrs())]
pub struct Foo {
    a: u8,
    b: Option<u8>,
    c: Option<Vec<u8>>,
}

The above code will generate the following code.

#[derive(Debug, PartialEq)]
pub struct PartialFoo {
    a: Option<u8>,
    b: Option<Option<u8>>,
    c: Option<Option<Vec<u8>>>,
}
#[derive(Debug, PartialEq)]
pub struct RequiredFoo {
    a: u8,
    b: u8,
    c: Vec<u8>,
}
#[derive(Debug, PartialEq)]
pub struct PickAB {
    a: u8,
    b: Option<u8>,
}
#[derive(Debug, PartialEq)]
pub struct OmitCD {
    a: u8,
    b: Option<u8>,
}

Some useful traits are also generated:

  • From<Foo> for PartialFoo, PickAB, OmitCD
  • From<PartialFoo> for Foo

Forwarding Attributes

To use this crate with other crates that need attributes, you can use the forward_attrs attribute to control which attributes are forwarded to the generated struct or enum.

use serde::{Deserialize, Serialize};
use utility_types::Omit;

#[derive(Debug, PartialEq, Serialize, Deserialize, Omit)]
#[omit(
    arg(
        ident = OmitCD,
        fields(c, d),
        derive(Debug, PartialEq, Serialize, Deserialize),
        forward_attrs(serde)
    )
)]
#[serde(rename_all = "UPPERCASE")]
pub struct Foo {
    a: u8,
    b: Option<u8>,
    c: Option<Vec<u8>>,
}

let omit_cd: OmitCD = serde_json::from_str(r#"{"A": 1, "B": 2}"#).unwrap();
assert_eq!(omit_cd, OmitCD { a: 1, b: Some(2) });

The behavior of the forward_attrs attribute is as follows:

  • If not provided, all attributes are forwarded by default.
  • If provided with a list of attributes, only the specified attributes are forwarded.
    • For example, forward_attrs(doc, serde) will forward only doc and serde.
    • If provided with only * (forward_attrs(*)), all attributes are forwarded.
    • If provided with an empty list (forward_attrs()), no attributes are forwarded.
  • If provided with a list inside not(), all attributes except the specified attributes are forwarded.
    • For example, forward_attrs(not(serde)) will forward all attributes except serde.

Known Issue

Currently I don't analyze which generic is used in the generated struct or enum. So rustc will complain if the field with generic is not included in the generated struct or enum.

Dependencies

~0.6–1MB
~23K SLoC