We are excited to announce v11.0.0!
Upgrading from v10.x.x
- With the
serde-compat
feature enabled (default), fields annotated with both#[serde(skip_serializing(_if))]
and#[serde(default)]
are now turned into optional properties.
See "Improved serde compatibility" under "New features" below - The API of the
ts_rs::TS
trait has slightly changed.
Some trivial adjustments to your code might be necessary, though only if you interact withts_rs::TS
directly.
Most users should not be affected by this.
New features
Everything's optional!
With v11, we introduce #[ts(optional_fields)]
, which can cut down on annoying boilerplace.
This attribute can be applied to structs and has the same effect as adding #[ts(optional)]
to every field.
Example:
#[derive(TS)]
#[ts(optional_fields)]
struct Form {
first_name: Option<String>, // first_name?: string
last_name: Option<String>, // last_name?: string
email: Option<String>, // email?: string
}
Improved serde compatibility
In the past, #[serde(skip_serializing)]
and #[serde(skip_serializing_if = "..")]
were ignored by ts-rs.
With v11, we now take these attributes into account, as long as they are used together with #[serde(default)]
.
This ensures that the generated type is valid for both serializing and deserializing rust structures by default.
A field annotated with #[serde(skip_serializing_(if))]
and #[serde(default)]
will be treated as if it was annotated with #[ts(optional = nullable)]
.
This behavior can be overridden using #[ts(optional = false)]
.
Example:
// now generates `type User = { nickname?: string | null }`,
// making it correct for both serialization and deserialization by default.
#[derive(Serialize, Deserialize, TS)]
struct User {
#[serde(skip_serializing_if = "Option::is_none", default)]
nickname: Option<String>,
}
More flexible attributes
#[doc = ..]
, #[ts(rename = "..")]
and #[ts(export_to = "..")]
now accept arbitrary expressions!
This enables some cool new patterns and makes integrating ts-rs in unusual setups easier.
Example:
// Renamed to the name of the current module
#[derive(TS)]
#[ts(rename = module_path!().rsplit_once("::").unwrap().1)]
struct Model;
// Comment containing the file path where the type was defined
#[derive(TS)]
#[doc = concat!("Defined in ", file!())]
struct UserGroup { . }
Optional tuple structs
The #[ts(optional)]
attribute can now also be applied to fields of tuple structs.
Example:
// generates `type Location = [Country, State, City?]`
#[derive(TS)]
struct Location(Country, State, #[ts(optional)] City);
Full changelog
- Add
#[ts(optional)]
to struct by @gustavo-shigueo in #366 - Add MSRV test to CI by @gustavo-shigueo in #381
- remove lazy_static by @ValiuchenkoVladyslav in #373
- Fix
#[ts(as = "...")]
dependency list by @gustavo-shigueo in #385 - Prevent naming collisions with by @gustavo-shigueo in #386
- Handle serde fail gracefully by @gustavo-shigueo in #389
- Merge same path imports by @gustavo-shigueo in #392
- Allow arbitrary expressions in top-level
#[ts(rename)]
by @NyxCode in #398 - Allow arbitrary expressions in
#[ts(export_to)]
by @NyxCode in #399 - Remove duplicate validation by @gustavo-shigueo in #404
- Allow arbitrary expressions in
#[doc]
by @NyxCode in #411 - Allow
#[ts(flatten)]
for fields of type HashMap by @gustavo-shigueo in #406 - Handle
serde(skip_serializing_if)
+serde(default)
by @manifest in #393 - release v11.0.0 by @NyxCode in #413
New Contributors
- @ValiuchenkoVladyslav made their first contribution in #373
- @manifest made their first contribution in #393