diff --git a/macros/src/types/named.rs b/macros/src/types/named.rs index ba167be5..6b9a2de3 100644 --- a/macros/src/types/named.rs +++ b/macros/src/types/named.rs @@ -102,6 +102,28 @@ fn format_field( return Ok(()); } + if let Some(ref type_override) = field_attr.type_override { + let field_name = to_ts_ident(field.ident.as_ref().unwrap()); + let name = match (field_attr.rename.as_ref(), rename_all) { + (Some(rn), _) => rn.to_owned(), + (None, Some(rn)) => rn.apply(&field_name), + (None, None) => field_name, + }; + let valid_name = raw_name_to_ts_field(name); + + // Start every doc string with a newline, because when other characters are in front, it is not "understood" by VSCode + let docs = match field_attr.docs.is_empty() { + true => "".to_string(), + false => format!("\n{}", &field_attr.docs), + }; + + formatted_fields.push(quote! { + format!("{}{}: {},", #docs, #valid_name, #type_override) + }); + + return Ok(()); + } + let ty = field_attr.type_as(&field.ty); let (optional_annotation, nullable) = match (struct_optional, field_attr.optional) { @@ -139,18 +161,13 @@ fn format_field( return Ok(()); } - let formatted_ty = field_attr - .type_override - .map(|t| quote!(#t)) - .unwrap_or_else(|| { - if field_attr.inline { - dependencies.append_from(&ty); - quote!(<#ty as #crate_rename::TS>::inline()) - } else { - dependencies.push(&ty); - quote!(<#ty as #crate_rename::TS>::name()) - } - }); + let formatted_ty = if field_attr.inline { + dependencies.append_from(&ty); + quote!(<#ty as #crate_rename::TS>::inline()) + } else { + dependencies.push(&ty); + quote!(<#ty as #crate_rename::TS>::name()) + }; let field_name = to_ts_ident(field.ident.as_ref().unwrap()); let name = match (field_attr.rename, rename_all) { diff --git a/ts-rs/tests/integration/optional_field.rs b/ts-rs/tests/integration/optional_field.rs index 46957d33..2bd7762f 100644 --- a/ts-rs/tests/integration/optional_field.rs +++ b/ts-rs/tests/integration/optional_field.rs @@ -104,6 +104,12 @@ struct OptionalStruct { e: Foo, f: Bar, + + #[ts(type = "string")] + g: Option, + + #[ts(as = "String")] + h: Option, } #[test] @@ -111,7 +117,7 @@ fn struct_optional() { assert_eq!( OptionalStruct::inline(), format!( - "{{ a?: number, b?: number, c?: number | null, d: number, e?: number, f?: number, }}" + "{{ a?: number, b?: number, c?: number | null, d: number, e?: number, f?: number, g: string, h: string, }}" ) ) } @@ -129,6 +135,12 @@ struct NullableStruct { e: Foo, f: Bar, + + #[ts(type = "string")] + g: Option, + + #[ts(as = "String")] + h: Option, } #[test] @@ -136,7 +148,7 @@ fn struct_nullable() { assert_eq!( NullableStruct::inline(), format!( - "{{ a?: number | null, b?: number | null, c?: number | null, d: number, e?: number | null, f?: number | null, }}" + "{{ a?: number | null, b?: number | null, c?: number | null, d: number, e?: number | null, f?: number | null, g: string, h: string, }}" ) ) }