diff --git a/macros/src/types/enum.rs b/macros/src/types/enum.rs index 2366e886..7f574de2 100644 --- a/macros/src/types/enum.rs +++ b/macros/src/types/enum.rs @@ -183,33 +183,33 @@ fn format_variant( format!("{{ \"{}\": \"{}\", \"{}\": {} }}", #tag, #ts_name, #content, #parsed_ty) ), }, - (false, Tagged::Internally { tag }) => match variant_type.inline_flattened { - Some(_) => { - quote! { #parsed_ty } + (false, Tagged::Internally { tag }) => match &variant.fields { + Fields::Unnamed(unnamed) if unnamed.unnamed.len() == 1 => { + let field = &unnamed.unnamed[0]; + let field_attr = FieldAttr::from_attrs(&unnamed.unnamed[0].attrs)?; + + field_attr.assert_validity(field)?; + + if field_attr.skip { + quote!(format!("{{ \"{}\": \"{}\" }}", #tag, #ts_name)) + } else { + let ty = match field_attr.type_override { + Some(type_override) => quote! { #type_override }, + None => { + let ty = field_attr.type_as(&field.ty); + quote!(<#ty as #crate_rename::TS>::name(cfg)) + } + }; + + quote!(format!("{{ \"{}\": \"{}\" }} & {}", #tag, #ts_name, #ty)) + } } - None => match &variant.fields { - Fields::Unnamed(unnamed) if unnamed.unnamed.len() == 1 => { - let field = &unnamed.unnamed[0]; - let field_attr = FieldAttr::from_attrs(&unnamed.unnamed[0].attrs)?; - - field_attr.assert_validity(field)?; - - if field_attr.skip { - quote!(format!("{{ \"{}\": \"{}\" }}", #tag, #ts_name)) - } else { - let ty = match field_attr.type_override { - Some(type_override) => quote! { #type_override }, - None => { - let ty = field_attr.type_as(&field.ty); - quote!(<#ty as #crate_rename::TS>::name(cfg)) - } - }; - - quote!(format!("{{ \"{}\": \"{}\" }} & {}", #tag, #ts_name, #ty)) - } + Fields::Unit => quote!(format!("{{ \"{}\": \"{}\" }}", #tag, #ts_name)), + _ => match variant_type.inline_flattened { + Some(_) => { + quote! { #parsed_ty } } - Fields::Unit => quote!(format!("{{ \"{}\": \"{}\" }}", #tag, #ts_name)), - _ => { + None => { quote!(format!("{{ \"{}\": \"{}\" }} & {}", #tag, #ts_name, #parsed_ty)) } }, diff --git a/macros/src/types/newtype.rs b/macros/src/types/newtype.rs index b4edb675..43a29b67 100644 --- a/macros/src/types/newtype.rs +++ b/macros/src/types/newtype.rs @@ -39,10 +39,15 @@ pub(crate) fn newtype( None => quote!(<#inner_ty as #crate_rename::TS>::name(cfg)), }; + let inline_flattened = match field_attr.type_override { + Some(_) => None, + None => Some(quote!(<#inner_ty as #crate_rename::TS>::inline_flattened(cfg))), + }; + Ok(DerivedTS { crate_rename: crate_rename.clone(), inline: inline_def, - inline_flattened: None, + inline_flattened, docs: attr.docs.clone(), dependencies, export: attr.export, diff --git a/macros/src/types/type_as.rs b/macros/src/types/type_as.rs index 44d31793..50f35182 100644 --- a/macros/src/types/type_as.rs +++ b/macros/src/types/type_as.rs @@ -20,7 +20,7 @@ pub(crate) fn type_as_struct( Ok(DerivedTS { crate_rename: crate_rename.clone(), inline: quote!(<#type_as as #crate_rename::TS>::inline(cfg)), - inline_flattened: None, + inline_flattened: Some(quote!(<#type_as as #crate_rename::TS>::inline_flattened(cfg))), docs: attr.docs.clone(), dependencies, export: attr.export, @@ -42,7 +42,7 @@ pub(crate) fn type_as_enum(attr: &EnumAttr, ts_name: Expr, type_as: &Type) -> Re Ok(DerivedTS { crate_rename: crate_rename.clone(), inline: quote!(<#type_as as #crate_rename::TS>::inline(cfg)), - inline_flattened: None, + inline_flattened: Some(quote!(<#type_as as #crate_rename::TS>::inline_flattened(cfg))), docs: attr.docs.clone(), dependencies, export: attr.export, diff --git a/ts-rs/tests/integration/main.rs b/ts-rs/tests/integration/main.rs index d2c85252..651e227d 100644 --- a/ts-rs/tests/integration/main.rs +++ b/ts-rs/tests/integration/main.rs @@ -45,6 +45,7 @@ mod lifetimes; mod list; mod merge_same_file_imports; mod nested; +mod newtype_flatten; mod optional_field; mod path_bug; mod ranges; @@ -69,6 +70,7 @@ mod top_level_type_as; mod top_level_type_override; mod tuple; mod type_as; +mod type_as_flatten; mod type_override; mod union; mod union_named_serde_skip; diff --git a/ts-rs/tests/integration/newtype_flatten.rs b/ts-rs/tests/integration/newtype_flatten.rs new file mode 100644 index 00000000..56561d35 --- /dev/null +++ b/ts-rs/tests/integration/newtype_flatten.rs @@ -0,0 +1,58 @@ +#![allow(dead_code)] + +use ts_rs::{Config, TS}; + +#[derive(TS)] +#[ts(export, export_to = "newtype_flatten/")] +struct Inner { + foo: String, + bar: i32, +} + +#[derive(TS)] +#[ts(export, export_to = "newtype_flatten/")] +struct NewtypeWrapper(Inner); + +#[derive(TS)] +#[ts(export, export_to = "newtype_flatten/")] +struct Outer { + name: String, + #[ts(flatten)] + inner: NewtypeWrapper, +} + +#[test] +fn test_newtype_flatten() { + let cfg = Config::from_env(); + assert_eq!(Inner::inline(&cfg), "{ foo: string, bar: number, }"); + assert_eq!(NewtypeWrapper::inline(&cfg), "Inner"); + assert_eq!( + Outer::inline(&cfg), + "{ name: string, foo: string, bar: number, }" + ); +} + +#[derive(TS)] +#[ts(export, export_to = "newtype_flatten/")] +struct InlinedNewtypeWrapper(#[ts(inline)] Inner); + +#[derive(TS)] +#[ts(export, export_to = "newtype_flatten/")] +struct OuterInlined { + name: String, + #[ts(flatten)] + inner: InlinedNewtypeWrapper, +} + +#[test] +fn test_newtype_flatten_inlined() { + let cfg = Config::from_env(); + assert_eq!( + InlinedNewtypeWrapper::inline(&cfg), + "{ foo: string, bar: number, }" + ); + assert_eq!( + OuterInlined::inline(&cfg), + "{ name: string, foo: string, bar: number, }" + ); +} diff --git a/ts-rs/tests/integration/type_as_flatten.rs b/ts-rs/tests/integration/type_as_flatten.rs new file mode 100644 index 00000000..3bec9835 --- /dev/null +++ b/ts-rs/tests/integration/type_as_flatten.rs @@ -0,0 +1,35 @@ +#![allow(dead_code)] + +use ts_rs::{Config, TS}; + +#[derive(TS)] +#[ts(export, export_to = "type_as_flatten/")] +struct Substitute { + alpha: String, + beta: i32, +} + +#[derive(TS)] +#[ts(as = "Substitute")] +#[ts(export, export_to = "type_as_flatten/")] +struct TypeWithAs { + _internal: String, +} + +#[derive(TS)] +#[ts(export, export_to = "type_as_flatten/")] +struct OuterWithTypeAs { + name: String, + #[ts(flatten)] + inner: TypeWithAs, +} + +#[test] +fn test_type_as_flatten() { + let cfg = Config::from_env(); + assert_eq!(TypeWithAs::inline(&cfg), "{ alpha: string, beta: number, }"); + assert_eq!( + OuterWithTypeAs::inline(&cfg), + "{ name: string, alpha: string, beta: number, }" + ); +}