diff --git a/Cargo.lock b/Cargo.lock index 628b292a..a978de9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -365,6 +365,15 @@ dependencies = [ "objc2", ] +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + [[package]] name = "bson" version = "3.1.0" @@ -1142,7 +1151,6 @@ checksum = "7b4a6248eb93a4401ed2f37dfe8ea592d3cf05b7cf4f8efa867b6895af7e094e" dependencies = [ "console", "once_cell", - "serde", "similar", "tempfile", ] @@ -1350,17 +1358,6 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" -[[package]] -name = "openapiv3" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8d427828b22ae1fff2833a03d8486c2c881367f1c336349f307f321e7f4d05" -dependencies = [ - "indexmap 2.14.0", - "serde", - "serde_json", -] - [[package]] name = "ordered-float" version = "5.3.0" @@ -1572,9 +1569,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.41.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce901f9a19d251159075a4c37af514c3b8ef99c22e02dd8c19161cf397ee94a" +checksum = "0c5108e3d4d903e21aac27f12ba5377b6b34f9f44b325e4894c7924169d06995" dependencies = [ "arrayvec", "num-traits", @@ -1719,11 +1716,12 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.19.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05839ce67618e14a09b286535c0d9c94e85ef25469b0e13cb4f844e5593eb19" +checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" dependencies = [ "base64", + "bs58", "chrono", "hex", "indexmap 1.9.3", @@ -1738,9 +1736,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.19.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2ebbe86054f9b45bc3881e865683ccfaccce97b9b4cb53f3039d67f355a334" +checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" dependencies = [ "darling", "proc-macro2", @@ -1866,35 +1864,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "specta-go" -version = "0.0.3" -dependencies = [ - "specta", - "specta-serde", -] - -[[package]] -name = "specta-jsonschema" -version = "0.0.3" -dependencies = [ - "insta", - "schemars 1.2.1", - "serde", - "serde_json", - "specta", - "specta-serde", - "specta-util", - "thiserror", -] - -[[package]] -name = "specta-kotlin" -version = "0.0.3" -dependencies = [ - "specta", -] - [[package]] name = "specta-macros" version = "2.0.0-rc.25" @@ -1905,14 +1874,6 @@ dependencies = [ "syn", ] -[[package]] -name = "specta-openapi" -version = "0.0.3" -dependencies = [ - "openapiv3", - "specta", -] - [[package]] name = "specta-serde" version = "0.0.12" @@ -2165,9 +2126,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.2" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "110a78583f19d5cdb2c5ccf321d1290344e71313c6c37d43520d386027d18386" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "pin-project-lite", ] diff --git a/specta-serde/src/lib.rs b/specta-serde/src/lib.rs index 838b68d7..e2caf802 100644 --- a/specta-serde/src/lib.rs +++ b/specta-serde/src/lib.rs @@ -1199,6 +1199,12 @@ fn rewrite_field_for_phase( { if let PhaseRewrite::Serialize = mode { field.optional = true; + + if attrs.skip_serializing_if.as_deref() == Some("Option::is_none") + && let Some(DataType::Nullable(inner)) = field.ty.take() + { + field.ty = Some(*inner); + } } // The attribute is meaningless on phase-split fields: the _Serialize // variant already has `optional = true`, and the _Deserialize variant @@ -1423,6 +1429,36 @@ fn enum_repr_already_rewritten(e: &Enum) -> bool { } fn variant_repr_already_rewritten(name: &str, variant: &Variant) -> bool { + // `transform_internal_variant` produces a tag of type `Primitive::str` when + // `widen_tag` is set (the `#[serde(other)]` variant in deserialize phase), + // and produces a tuple-variant body of `Intersection<{tag-struct}, payload>` + // for non-empty unnamed variants. Without recognizing both shapes, the + // second-pass guard on internally-tagged enums containing such variants + // fails. The whole enum then gets re-transformed -- this time as + // `EnumRepr::External`, because the first pass cleared `e.attributes` -- + // producing wrong externally-tagged TS bindings for what serde actually + // emits as internally-tagged JSON. + fn is_rewritten_tag_ty(ty: &DataType) -> bool { + is_generated_string_literal_datatype(ty) + || matches!(ty, DataType::Primitive(Primitive::str)) + } + + fn is_rewritten_internal_intersection(ty: &DataType) -> bool { + let DataType::Intersection(parts) = ty else { + return false; + }; + let Some(DataType::Struct(s)) = parts.first() else { + return false; + }; + let Fields::Named(named) = &s.fields else { + return false; + }; + named + .fields + .iter() + .any(|(_, field)| field.ty.as_ref().is_some_and(is_rewritten_tag_ty)) + } + match &variant.fields { Fields::Unit => false, Fields::Unnamed(fields) if name.is_empty() => unnamed_live_field_count(fields) == 1, @@ -1430,13 +1466,11 @@ fn variant_repr_already_rewritten(name: &str, variant: &Variant) -> bool { .fields .first() .and_then(|field| field.ty.as_ref()) - .is_some_and(is_generated_string_literal_datatype), + .is_some_and(|ty| { + is_generated_string_literal_datatype(ty) || is_rewritten_internal_intersection(ty) + }), Fields::Named(fields) => fields.fields.iter().any(|(field_name, field)| { - field_name == name - || field - .ty - .as_ref() - .is_some_and(is_generated_string_literal_datatype) + field_name == name || field.ty.as_ref().is_some_and(is_rewritten_tag_ty) }), _ => false, } @@ -1870,6 +1904,40 @@ fn transform_internal_variant( match &variant.fields { Fields::Unit => {} Fields::Named(named) => { + // If any named field is `#[serde(flatten)]`, serde merges its + // contents at the variant's top level alongside the tag. Mirror + // the unnamed-payload path: build an Intersection of `{tag}`, + // each flattened field's payload type, and (if any) a struct of + // the remaining non-flattened fields. Without this, the flatten + // attribute survives to the typescript exporter, which writes + // the field literally as `inner: T` instead of merging it. + let has_flattened = named + .fields + .iter() + .any(|(_, field)| field_is_flattened(field)); + if has_flattened { + let mut payload_parts: Vec = Vec::new(); + let mut leftover: Vec<(Cow<'static, str>, Field)> = Vec::new(); + for (name, field) in named.fields.iter().cloned() { + if field_is_flattened(&field) { + if let Some(ty) = field.ty { + payload_parts.push(ty); + } + } else { + leftover.push((name, field)); + } + } + let mut intersection = Vec::with_capacity(payload_parts.len() + 2); + intersection.push(named_fields_datatype(fields)); + if !leftover.is_empty() { + intersection.push(named_fields_datatype(leftover)); + } + intersection.extend(payload_parts); + return Ok(clone_variant_with_unnamed_fields( + variant, + vec![Field::new(DataType::Intersection(intersection))], + )); + } fields.extend(named.fields.iter().cloned()); } Fields::Unnamed(unnamed) => { @@ -2621,6 +2689,29 @@ mod tests { )); } + #[test] + fn skip_serializing_if_option_is_none_omits_null_in_serialize_phase() { + let mut types = specta::Types::default(); + let dt = WithSkipIf::definition(&mut types); + let resolved = formatted_phases(types); + + let serialize = select_phase_datatype(&dt, &resolved, Phase::Serialize); + let deserialize = select_phase_datatype(&dt, &resolved, Phase::Deserialize); + + let serialize_field = named_field(&serialize, &resolved, "nickname"); + let deserialize_field = named_field(&deserialize, &resolved, "nickname"); + + assert!(serialize_field.optional); + assert!(!matches!( + serialize_field.ty.as_ref(), + Some(DataType::Nullable(_)) + )); + assert!(matches!( + deserialize_field.ty.as_ref(), + Some(DataType::Nullable(_)) + )); + } + #[test] fn phase_split_field_passes_unified_mode_validation() { // Regression test for the interaction with downstream callers (e.g. @@ -2670,6 +2761,17 @@ mod tests { } fn named_field_type<'a>(dt: &'a DataType, types: &'a Types, field_name: &str) -> &'a DataType { + named_field(dt, types, field_name) + .ty + .as_ref() + .expect("field should have a type") + } + + fn named_field<'a>( + dt: &'a DataType, + types: &'a Types, + field_name: &str, + ) -> &'a specta::datatype::Field { let DataType::Reference(specta::datatype::Reference::Named(reference)) = dt else { panic!("expected named reference"); }; @@ -2685,7 +2787,7 @@ mod tests { fields .fields .iter() - .find_map(|(name, field)| (name == field_name).then_some(field.ty.as_ref()).flatten()) + .find_map(|(name, field)| (name == field_name).then_some(field)) .expect("field should exist") } diff --git a/tests/tests/serde_conversions.rs b/tests/tests/serde_conversions.rs index 17bc4a8b..20edbce9 100644 --- a/tests/tests/serde_conversions.rs +++ b/tests/tests/serde_conversions.rs @@ -84,6 +84,13 @@ struct SkipSerializingIfOnly { value: Option, } +#[derive(Type, Serialize, Deserialize)] +#[specta(collect = false)] +struct DefaultedSkipSerializingIfOnly { + #[serde(default, skip_serializing_if = "Option::is_none")] + value: Option, +} + #[derive(Type, Serialize, Deserialize)] #[specta(collect = false)] enum TupleVariantSkipSerializingIfOnly { @@ -412,6 +419,23 @@ fn skip_serializing_if_requires_phases() { .expect("PhasesFormat should accept skip_serializing_if"); } +#[test] +fn option_is_none_omits_null_in_serialize_phase() { + let rendered = Typescript::default() + .export( + &Types::default() + .register::() + .register::(), + specta_serde::PhasesFormat, + ) + .expect("PhasesFormat should split skip_serializing_if phases"); + + insta::assert_snapshot!( + "serde-conversions-format-phases-option-is-none-omits-null", + rendered + ); +} + #[test] fn tuple_variant_skip_serializing_if_requires_phases_and_splits_owner() { let err = Typescript::default() diff --git a/tests/tests/snapshots/test__jsdoc__export-many-serde.snap b/tests/tests/snapshots/test__jsdoc__export-many-serde.snap index df7f9467..81d14785 100644 --- a/tests/tests/snapshots/test__jsdoc__export-many-serde.snap +++ b/tests/tests/snapshots/test__jsdoc__export-many-serde.snap @@ -1,5 +1,6 @@ --- source: tests/tests/jsdoc.rs +assertion_line: 143 expression: output --- /** @@ -729,8 +730,12 @@ expression: output * }} C * @property {First} D * - * @typedef {{ type: "Variant"; inner: First }} MyEnumTagged - * @property {{ type: "Variant"; inner: First }} Variant + * @typedef {{ + * type: "Variant", + * } & First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & First} Variant * * @typedef {{ Variant: { * inner: First, diff --git a/tests/tests/snapshots/test__jsdoc__export-many-serde_phases.snap b/tests/tests/snapshots/test__jsdoc__export-many-serde_phases.snap index c411a635..8e5476a2 100644 --- a/tests/tests/snapshots/test__jsdoc__export-many-serde_phases.snap +++ b/tests/tests/snapshots/test__jsdoc__export-many-serde_phases.snap @@ -1,5 +1,6 @@ --- source: tests/tests/jsdoc.rs +assertion_line: 143 expression: output --- /** @@ -779,8 +780,12 @@ expression: output * }} C * @property {First} D * - * @typedef {{ type: "Variant"; inner: First }} MyEnumTagged - * @property {{ type: "Variant"; inner: First }} Variant + * @typedef {{ + * type: "Variant", + * } & First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & First} Variant * * @typedef {{ Variant: { * inner: First, diff --git a/tests/tests/snapshots/test__jsdoc__export-serde.snap b/tests/tests/snapshots/test__jsdoc__export-serde.snap index e219aab6..4d7bbb44 100644 --- a/tests/tests/snapshots/test__jsdoc__export-serde.snap +++ b/tests/tests/snapshots/test__jsdoc__export-serde.snap @@ -1,5 +1,6 @@ --- source: tests/tests/jsdoc.rs +assertion_line: 114 expression: output --- Range: /** @@ -986,8 +987,12 @@ Tenth: /** */ MyEnumTagged: /** - * @typedef {{ type: "Variant"; inner: First }} MyEnumTagged - * @property {{ type: "Variant"; inner: First }} Variant + * @typedef {{ + * type: "Variant", + * } & First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & First} Variant */ MyEnumExternal: /** diff --git a/tests/tests/snapshots/test__jsdoc__export-serde_phases.snap b/tests/tests/snapshots/test__jsdoc__export-serde_phases.snap index d92fe098..a34797a5 100644 --- a/tests/tests/snapshots/test__jsdoc__export-serde_phases.snap +++ b/tests/tests/snapshots/test__jsdoc__export-serde_phases.snap @@ -1,5 +1,6 @@ --- source: tests/tests/jsdoc.rs +assertion_line: 114 expression: output --- Issue374: /** @@ -1060,8 +1061,12 @@ Tenth: /** */ MyEnumTagged: /** - * @typedef {{ type: "Variant"; inner: First }} MyEnumTagged - * @property {{ type: "Variant"; inner: First }} Variant + * @typedef {{ + * type: "Variant", + * } & First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & First} Variant */ MyEnumExternal: /** diff --git a/tests/tests/snapshots/test__jsdoc__inline-serde.snap b/tests/tests/snapshots/test__jsdoc__inline-serde.snap index e9a32b86..c3db4f65 100644 --- a/tests/tests/snapshots/test__jsdoc__inline-serde.snap +++ b/tests/tests/snapshots/test__jsdoc__inline-serde.snap @@ -1,5 +1,6 @@ --- source: tests/tests/jsdoc.rs +assertion_line: 191 expression: output --- i8: number @@ -425,7 +426,9 @@ Ninth: { t: "A"; c: string } | { t: "B" } | { t: "C"; c: { Tenth: string | "B" | { a: string, } | First -MyEnumTagged: { type: "Variant"; inner: First } +MyEnumTagged: { + type: "Variant", +} & First MyEnumExternal: { Variant: { inner: First, } } diff --git a/tests/tests/snapshots/test__jsdoc__inline-serde_phases.snap b/tests/tests/snapshots/test__jsdoc__inline-serde_phases.snap index db5dbd89..c35dbb41 100644 --- a/tests/tests/snapshots/test__jsdoc__inline-serde_phases.snap +++ b/tests/tests/snapshots/test__jsdoc__inline-serde_phases.snap @@ -9,7 +9,7 @@ Issue374: { Optional: { a: number | null, b?: number | null, - c?: string | null, + c?: string, d: boolean, } StructPhaseSpecificRename: { @@ -458,7 +458,9 @@ Ninth: { t: "A"; c: string } | { t: "B" } | { t: "C"; c: { Tenth: string | "B" | { a: string, } | First -MyEnumTagged: { type: "Variant"; inner: First } +MyEnumTagged: { + type: "Variant", +} & First MyEnumExternal: { Variant: { inner: First, } } diff --git a/tests/tests/snapshots/test__jsdoc__inline-serde_phases.snap.new b/tests/tests/snapshots/test__jsdoc__inline-serde_phases.snap.new new file mode 100644 index 00000000..ee610f67 --- /dev/null +++ b/tests/tests/snapshots/test__jsdoc__inline-serde_phases.snap.new @@ -0,0 +1,696 @@ +--- +source: tests/tests/jsdoc.rs +assertion_line: 191 +expression: output +--- +Issue374: { + foo?: boolean, + bar?: boolean, +} +Optional: { + a: number | null, + b?: number | null, + c?: string, + d: boolean, +} +StructPhaseSpecificRename: { + kind: "StructPhaseSpecificRenameSerialize", + ser: string, +} +StructWithAlias: { + field: string, +} +StructWithMultipleAliases: { + field: string, +} +StructWithAliasAndRename: { + renamed_field: string, +} +EnumWithVariantAlias: "Variant" | "Other" +EnumWithMultipleVariantAliases: "Variant" | "Other" +EnumWithVariantAliasAndRename: "renamed_variant" | "Other" +InternallyTaggedWithAlias: ({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never } +AdjacentlyTaggedWithAlias: { type: "A"; data: { + field: string, +} } | { type: "B"; data: { + other: number, +} } +UntaggedWithAlias: ({ field: string }) & { other?: never } | ({ other: number }) & { field?: never } +i8: number +i16: number +i32: number +u8: number +u16: number +u32: number +f32: number | null +f64: number | null +bool: boolean +char: string +Range: { + start: T, + end: T, +} +RangeInclusive: { + start: T, + end: T, +} +(): null +(String, i32): [string, number] +(String, i32, bool): [string, number, boolean] +((String, i32), (bool, char, bool), ()): [[string, number], [boolean, string, boolean], null] +(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool): [boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean] +(Vec, Vec): [number[], boolean[]] +String: string +PathBuf: string +IpAddr: string +Ipv4Addr: string +Ipv6Addr: string +SocketAddr: string +SocketAddrV4: string +SocketAddrV6: string +Cow<'static, str>: string +Cow<'static, i32>: number +&'static str: string +&'static bool: boolean +&'static i32: number +Vec: number[] +&'static [i32]: number[] +&'static [i32; 3]: [number, number, number] +[i32; 3]: [number, number, number] +Vec: MyEnum[] +&'static [MyEnum]: MyEnum[] +&'static [MyEnum; 6]: [MyEnum, MyEnum, MyEnum, MyEnum, MyEnum, MyEnum] +[MyEnum; 2]: [MyEnum, MyEnum] +&'static [i32; 1]: [number] +&'static [i32; 0]: [] +Option: number | null +Option<()>: null +Option>: number[] | null +Result: { + ok: T, + err: E, +} +Vec>>: (number | null)[] +Option>>: number[] | null +[Vec; 3]: [string[], string[], string[]] +Option>: string | null +Option>>: string | null +PhantomData<()>: null +PhantomData: null +Infallible: never +Unit1: null +Unit2: Record +Unit3: [] +Unit4: null +Unit5: "A" +Unit6: { A: null } +Unit7: { A: Record } +SimpleStruct: { + a: number, + b: string, + c: [number, string, number], + d: string[], + e: string | null, +} +TupleStruct1: number +TupleStruct3: [number, boolean, string] +TestEnum: "Unit" | ({ Single: number }) & { Multiple?: never; Struct?: never } | ({ Multiple: [number, number] }) & { Single?: never; Struct?: never } | ({ Struct: { + a: number, +} }) & { Multiple?: never; Single?: never } +RefStruct: TestEnum +InlinerStruct: { + inline_this: { + ref_struct: SimpleStruct, + val: number, + }, + dont_inline_this: RefStruct, +} +GenericStruct: { + arg: T, +} +GenericStruct: { + arg: T, +} +FlattenEnumStruct: ({ + outer: string, +}) & (FlattenEnum) +OverridenStruct: { + overriden_field: string, +} +HasGenericAlias: { [key in number]: string } +EnumMacroAttributes: ({ A: string }) & { D?: never; bbb?: never; cccc?: never } | ({ bbb: number }) & { A?: never; D?: never; cccc?: never } | ({ cccc: number }) & { A?: never; D?: never; bbb?: never } | ({ D: { + a: string, + bbbbbb: number, +} }) & { A?: never; bbb?: never; cccc?: never } +InlineEnumField: { A: { + a: string, +} } +InlineOptionalType: { + optional_field: { + a: string, +} | null, +} +Rename: "OneWord" | "Two words" +TransparentType: TransparentTypeInner +TransparentType2: null +TransparentTypeWithOverride: string +[Option; 3]: [(number | null), (number | null), (number | null)] +HashMap: Partial<{ [key in BasicEnum]: null }> +HashMap: Partial<{ [key in BasicEnum]: number }> +Option>>>: number | null +Vec: PlaceholderInnerField[] +EnumReferenceRecordKey: { + a: Partial<{ [key in BasicEnum]: number }>, +} +FlattenOnNestedEnum: ({ + id: string, +}) & (NestedEnum) +MyEmptyInput: Record +(String): string +(String,): [string] +ExtraBracketsInTupleVariant: { A: string } +ExtraBracketsInUnnamedStruct: string +Vec: MyEnum[] +InlineTuple: { + demo: [string, boolean], +} +InlineTuple2: { + demo: [{ + demo: [string, boolean], +}, boolean], +} +Box: string +Box: string +SkippedFieldWithinVariant: { type: "A" } | { type: "B"; data: string } +KebabCase: { + "test-ing": string, +} +&[&str]: string[] +Issue281<'_>: { + default_unity_arguments: string[], +} +LifetimeGenericStruct<'_, i32>: { + borrowed: T[], + owned: T[], +} +LifetimeGenericEnum<'_, i32>: ({ Borrowed: T }) & { Owned?: never } | ({ Owned: T }) & { Borrowed?: never } +RenameWithWeirdCharsField: { + "@odata.context": string, +} +RenameWithWeirdCharsVariant: { "@odata.context": string } +RenamedFieldKeys: { + "": string, + "a\"b": string, + "a\\b": string, + "line\nbreak": string, + "line\u2028break": string, + "line\u2029break": string, +} +RenamedVariantWithSkippedPayload: "a-b" +type_type::Type: never +ActualType: { + a: GenericType, +} +SpectaTypeOverride: { + string_ident: string, + u32_ident: number, + path: string, + tuple: [string, number], +} +ContainerTypeOverrideStruct: string +ContainerTypeOverrideEnum: string +ContainerTypeOverrideGeneric>: string +ContainerTypeOverrideToGeneric: T +ContainerTypeOverrideTuple: [string, number] +ContainerTypeOverrideTupleGeneric: [T, string] +InvalidToValidType: { + cause: null, +} +TupleStruct: string +TupleStructWithRep: string +GenericTupleStruct: T +BracedStruct: string +Struct: { + t: "StructNew", + a: string, +} +Struct2: { + b: string, +} +Enum: { t: "A" } | { t: "B" } +Enum2: { t: "C" } | { t: "B" } | { t: "D"; enumField: null } +Enum3: { t: "A"; b: string } +StructRenameAllUppercase: { + A: number, + B: number, +} +RenameSerdeSpecialChar: { + "a/b": number, +} +EnumRenameAllUppercase: "HELLOWORLD" | "VARIANTB" | "TESTINGWORDS" +Recursive: { + demo: Recursive, +} +RecursiveMapValue: { + demo: { [key in string]: RecursiveMapValue }, +} +RecursiveTransparent: RecursiveInline +RecursiveInEnum: { A: { + demo: RecursiveInEnum, +} } +NonOptional: string | null +OptionalOnNamedField: string | null +OptionalOnTransparentNamedField: { + b: string | null, +} +OptionalInEnum: ({ A?: string | null }) & { B?: never; C?: never } | ({ B: { + a: string | null, +} }) & { A?: never; C?: never } | ({ C: { + a?: string | null, +} }) & { A?: never; B?: never } +UntaggedVariants: string | number | { id: string } | [string, boolean] +UntaggedVariantsWithoutValue: string | [number, string] | number +UntaggedVariantsWithDuplicateBranches: null | number +HashMap: { [key in string]: null } +Regular: { [key in string]: null } +HashMap: { [key in never]: null } +HashMap: { [key in TransparentStruct]: null } +HashMap: Partial<{ [key in UnitVariants]: null }> +HashMap: Partial<{ [key in UntaggedVariantsKey]: null }> +ValidMaybeValidKey: { [key in MaybeValidKey]: null } +ValidMaybeValidKeyNested: { [key in MaybeValidKey>]: null } +MacroStruct: string +MacroStruct2: { + demo: string, +} +MacroEnum: ({ Demo: string }) & { Demo2?: never } | ({ Demo2: { + demo2: string, +} }) & { Demo?: never } +DeprecatedType: { + a: number, +} +DeprecatedTypeWithMsg: { + a: number, +} +DeprecatedTypeWithMsg2: { + a: number, +} +DeprecatedFields: { + a: number, + /** + * @deprecated + */ + b: string, + /** + * @deprecated This field is cringe! + */ + c: string, + /** + * @deprecated This field is cringe! + */ + d: string, +} +DeprecatedTupleVariant: [ +/** + * @deprecated + */ +string, +/** + * @deprecated Nope + */ +string, +/** + * @deprecated Nope + */ +number] +DeprecatedEnumVariants: +/** + * @deprecated + */ +"A" | +/** + * @deprecated Nope + */ +"B" | +/** + * @deprecated Nope + */ +"C" +CommentedStruct: { + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + a: number, +} +CommentedEnum: +/** + * Some triple-slash comment + * Some more triple-slash comment + */ +({ A: number }) & { B?: never } | +/** + * Some triple-slash comment + * Some more triple-slash comment + */ +({ B: { + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + a: number, +} }) & { A?: never } +SingleLineComment: +/** Some single-line comment */ +({ A: number }) & { B?: never } | +/** Some single-line comment */ +({ B: { + /** Some single-line comment */ + a: number, +} }) & { A?: never } +NonGeneric: { + a: A, + b: B, +} +HalfGenericA: { + a: A, + b: B, +} +HalfGenericB: { + a: A, + b: B, +} +FullGeneric: { + a: A, + b: B, +} +Another: { + a: A, + b: B, +} +MapA: { [key in string]: number } +MapB: { [key in number]: string } +MapC: { [key in string]: AGenericStruct } +AGenericStruct: { + field: { + a: A, + b: B, +}, +} +A: { + a: B, + b: { + b: number, + }, + c: B, + d: { + flattened: number, + }, + e: { + generic_flattened: number, + }, +} +DoubleFlattened: { + a: ToBeFlattened, + b: ToBeFlattened, +} +FlattenedInner: (Inner) +BoxFlattened: (BoxedInner) +BoxInline: { + c: { + a: number, + }, +} +First: { + a: string, +} +Second: { + a: number, +} +Third: ({ + b: { [key in string]: string }, + c: First, +}) & (First) +Fourth: { + a: First, + b: { + a: string, + }, +} +TagOnStructWithInline: { + type: "TagOnStructWithInline", + a: First, + b: { + a: string, + }, +} +Sixth: { + a: First, + b: First, +} +Seventh: { + a: First, + b: Second, +} +Eight: { A: string } | "B" +Ninth: { t: "A"; c: string } | { t: "B" } | { t: "C"; c: { + a: string, +} } | { t: "D"; c: First } +Tenth: string | "B" | { + a: string, +} | First +MyEnumTagged: { + type: "Variant", +} & First +MyEnumExternal: { Variant: { + inner: First, +} } +MyEnumAdjacent: { t: "Variant"; c: { + inner: First, +} } +MyEnumUntagged: { inner: First } +EmptyStruct: Record +EmptyStructWithTag: { + a: "EmptyStructWithTag", +} +AdjacentlyTagged: { t: "A" } | { t: "B"; c: { + id: string, + method: string, +} } | { t: "C"; c: string } +LoadProjectEvent: { event: "started"; data: { + projectName: string, +} } | { event: "progressTest"; data: { + projectName: string, + status: string, + progress: number, +} } | { event: "finished"; data: { + projectName: string, +} } +ExternallyTagged: "A" | ({ B: { + id: string, + method: string, +} }) & { C?: never } | ({ C: string }) & { B?: never } +Issue221External: ({ A: { + a: string, +} }) & { B?: never } | ({ B: { + b: string, +} }) & { A?: never } +InternallyTaggedD: { + type: "A", +} & { [key in string]: string } +InternallyTaggedE: { type: "A" } +InternallyTaggedF: { type: "A" } +InternallyTaggedH: { type: "A" } +InternallyTaggedL: { + type: "A", +} & { type: "A" } | { type: "B" } +InternallyTaggedM: { type: "A" } +Issue221UntaggedSafe: ({ a: string }) & { b?: never } | ({ b: string }) & { a?: never } +Issue221UntaggedMixed: ({ a: string }) & { b?: never; values?: never } | ({ b: string }) & { a?: never; values?: never } | ({ values: { [key in string]: string } }) & { a?: never; b?: never } +EmptyEnum: never +EmptyEnumTagged: never +EmptyEnumTaggedWContent: never +EmptyEnumUntagged: never +SkipOnlyField: Record +SkipField: { + b: number, +} +SkipVariant: { A: string } +SkipUnnamedFieldInVariant: "A" | { B: [number] } +SkipNamedFieldInVariant: ({ A: Record }) & { B?: never } | ({ B: { + b: number, +} }) & { A?: never } +TransparentWithSkip: null +TransparentWithSkip2: string +TransparentWithSkip3: string +SkipVariant2: { tag: "A"; data: string } +SkipVariant3: { A: { + a: string, +} } +SkipStructFields: { + a: number, +} +SpectaSkipNonTypeField: { + a: number, +} +FlattenA: { + a: number, + b: number, +} +FlattenB: ({ + c: number, +}) & (FlattenA) +FlattenC: ({ + c: number, +}) & (FlattenA) +FlattenD: { + a: FlattenA, + c: number, +} +FlattenE: { + b: ({ + c: number, + }) & (FlattenA), + d: number, +} +FlattenF: { + b: ({ + c: number, + }) & (FlattenA), + d: number, +} +FlattenG: { + b: FlattenB, + d: number, +} +TupleNested: [number[], [number[], number[]], [number[], number[], number[]]] +Generic1<()>: { + value: T, + values: T[], +} +GenericAutoBound<()>: { + value: T, + values: T[], +} +GenericAutoBound2<()>: { + value: T, + values: T[], +} +Container1: { + foo: Generic1, + bar: Generic1[], + baz: { [key in string]: Generic1 }, +} +Generic2<(), String, i32>: ({ A: A }) & { B?: never; C?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ B: [B, B, B] }) & { A?: never; C?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ C: C[] }) & { A?: never; B?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ D: A[][][] }) & { A?: never; B?: never; C?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ E: { + a: A, + b: B, + c: C, +} }) & { A?: never; B?: never; C?: never; D?: never; X?: never; Y?: never; Z?: never } | ({ X: number[] }) & { A?: never; B?: never; C?: never; D?: never; E?: never; Y?: never; Z?: never } | ({ Y: number }) & { A?: never; B?: never; C?: never; D?: never; E?: never; X?: never; Z?: never } | ({ Z: number[][] }) & { A?: never; B?: never; C?: never; D?: never; E?: never; X?: never; Y?: never } +GenericNewType1<()>: T[][] +GenericTuple<()>: [T, T[], T[][]] +GenericStruct2<()>: { + a: T, + b: [T, T], + c: [T, [T, T]], + d: [T, T, T], + e: [([T, T]), ([T, T]), ([T, T])], + f: T[], + g: T[][], + h: ([([T, T]), ([T, T]), ([T, T])])[], +} +InlineGenericNewtype: string +InlineGenericNested: [string, string[], [string, string], { [key in string]: string }, string | null, "Unit" | ({ Unnamed: string }) & { Named?: never } | ({ Named: { + value: string, +} }) & { Unnamed?: never }] +InlineFlattenGenericsG<()>: { + t: T, +} +InlineFlattenGenerics: ({ + g: InlineFlattenGenericsG, + gi: { + t: string, + }, +}) & (InlineFlattenGenericsG) +GenericDefault: { + value: T, +} +ChainedGenericDefault: { + first: T, + second: U, +} +ChainedGenericDefault: { + first: T, + second: U, +} +ChainedGenericDefault: { + first: T, + second: U, +} +ChainedGenericDefault: { + first: T, + second: U, +} +GenericDefaultSkipped: { + value: T, +} +GenericDefaultSkippedNonType: { + value: number, +} +GenericParameterOrderPreserved: { + pair: Pair, +} +ConstGenericInNonConstContainer: { + data: [number], + a: [number, number], + d: [number, number], +} +ConstGenericInConstContainer: { + data: number[], + a: number[], + d: [number, number], +} +NamedConstGenericContainer: { + a: NamedConstGeneric, + b: NamedConstGeneric, + d: [number, number], +} +InlineConstGenericContainer: { + b: { + data: [number, number], + a: [number, number], + d: [number, number, number], + }, + c: { + data: [number, number, number], + a: [number, number], + d: [number, number, number], + }, + d: [number, number], +} +InlineRecursiveConstGenericContainer: { + b: { + data: [number, number], + a: [number, number], + d: [number, number, number], + e: InlineRecursiveConstGeneric, + }, + c: { + data: [number, number, number], + a: [number, number], + d: [number, number, number], + e: InlineRecursiveConstGeneric, + }, + d: [number, number], +} +TestCollectionRegister: never +TestCollectionRegister: never +specta_typescript::Any: any +specta_typescript::Any: any +specta_typescript::Unknown: unknown +specta_typescript::Unknown: unknown +specta_typescript::Never: never +specta_typescript::Never: never +specta_typescript::Number: number +specta_typescript::Number: number +specta_typescript::BigInt: bigint +specta_typescript::BigInt: bigint diff --git a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-files-serde.snap b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-files-serde.snap index fe23c480..bb07e552 100644 --- a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-files-serde.snap +++ b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-files-serde.snap @@ -1,5 +1,6 @@ --- source: tests/tests/jsdoc.rs +assertion_line: 78 expression: output --- std/ @@ -46,7 +47,7 @@ test/ */ ════════════════════════════════════════ - types.js (28921 bytes) + types.js (28925 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. /** @@ -869,8 +870,12 @@ test/ * inner: First, * } }} Variant * - * @typedef {{ type: "Variant"; inner: First }} MyEnumTagged - * @property {{ type: "Variant"; inner: First }} Variant + * @typedef {{ + * type: "Variant", + * } & First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & First} Variant * * @typedef {{ inner: First }} MyEnumUntagged * @property {{ inner: First }} Variant diff --git a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-files-serde_phases.snap b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-files-serde_phases.snap index a90825b1..f8e3058f 100644 --- a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-files-serde_phases.snap +++ b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-files-serde_phases.snap @@ -46,7 +46,7 @@ test/ */ ════════════════════════════════════════ - types.js (37153 bytes) + types.js (37055 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. /** @@ -838,27 +838,21 @@ test/ * @property {InternallyTaggedWithAlias_Serialize} Serialize * @property {InternallyTaggedWithAlias_Deserialize} Deserialize * - * @typedef {({ A: { + * @typedef {{ * type: "A", * } & { * field: string, * } | { * bruh: string, - * } }) & { B?: never } | ({ B: { - * type: "B", - * other: number, - * } }) & { A?: never }} InternallyTaggedWithAlias_Deserialize - * @property {{ A: { + * } | { type: "B"; other: number }} InternallyTaggedWithAlias_Deserialize + * @property {{ * type: "A", * } & { * field: string, * } | { * bruh: string, - * } }} A - * @property {{ B: { - * type: "B", - * other: number, - * } }} B + * }} A + * @property {{ type: "B"; other: number }} B * * @typedef {({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }} InternallyTaggedWithAlias_Serialize * @property {{ type: "A"; field: string }} A @@ -995,8 +989,12 @@ test/ * inner: First, * } }} Variant * - * @typedef {{ type: "Variant"; inner: First }} MyEnumTagged - * @property {{ type: "Variant"; inner: First }} Variant + * @typedef {{ + * type: "Variant", + * } & First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & First} Variant * * @typedef {{ inner: First }} MyEnumUntagged * @property {{ inner: First }} Variant @@ -1075,12 +1073,12 @@ test/ * @typedef {{ * a: number | null, * b?: number | null, - * c?: string | null, + * c?: string, * d: boolean, * }} Optional_Serialize * @property {number | null} a * @property {number | null} [b] - * @property {string | null} [c] + * @property {string} [c] * @property {boolean} d * * @typedef {{ diff --git a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-files-serde_phases.snap.new b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-files-serde_phases.snap.new new file mode 100644 index 00000000..08147a8a --- /dev/null +++ b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-files-serde_phases.snap.new @@ -0,0 +1,2097 @@ +--- +source: tests/tests/jsdoc.rs +assertion_line: 78 +expression: output +--- +std/ + ops.js (295 bytes) + ──────────────────────────────────────── + // This file has been generated by Specta. Do not edit this file manually. + /** + * @typedef {{ + * start: T, + * end: T, + * }} Range + * @property {T} start + * @property {T} end + * + * @typedef {{ + * start: T, + * end: T, + * }} RangeInclusive + * @property {T} start + * @property {T} end + */ + ════════════════════════════════════════ + + result.js (181 bytes) + ──────────────────────────────────────── + // This file has been generated by Specta. Do not edit this file manually. + /** + * @typedef {{ + * ok: T, + * err: E, + * }} Result + * @property {T} ok + * @property {E} err + */ + ════════════════════════════════════════ + +test/ + types/ + type_type.js (108 bytes) + ──────────────────────────────────────── + // This file has been generated by Specta. Do not edit this file manually. + /** + * @typedef {never} Type + */ + ════════════════════════════════════════ + + types.js (37055 bytes) + ──────────────────────────────────────── + // This file has been generated by Specta. Do not edit this file manually. + /** + * @typedef {{ + * a: B, + * b: { + * b: number, + * }, + * c: B, + * d: { + * flattened: number, + * }, + * e: { + * generic_flattened: number, + * }, + * }} A + * @property {B} a + * @property {{ + * b: number, + * }} b + * @property {B} c + * @property {{ + * flattened: number, + * }} d + * @property {{ + * generic_flattened: number, + * }} e + * + * @typedef {{ + * field: Demo, + * }} AGenericStruct + * @property {Demo} field + * + * @typedef {{ + * a: GenericType, + * }} ActualType + * @property {GenericType} a + * + * @typedef {{ t: "A" } | { t: "B"; c: { + * id: string, + * method: string, + * } } | { t: "C"; c: string }} AdjacentlyTagged + * @property {{ t: "A" }} A + * @property {{ t: "B"; c: { + * id: string, + * method: string, + * } }} B + * @property {{ t: "C"; c: string }} C + * + * @typedef {AdjacentlyTaggedWithAlias_Serialize | AdjacentlyTaggedWithAlias_Deserialize} AdjacentlyTaggedWithAlias + * @property {AdjacentlyTaggedWithAlias_Serialize} Serialize + * @property {AdjacentlyTaggedWithAlias_Deserialize} Deserialize + * + * @typedef {{ type: "A"; data: { + * field: string, + * } | { + * bruh: string, + * } } | { type: "B"; data: { + * other: number, + * } }} AdjacentlyTaggedWithAlias_Deserialize + * @property {{ type: "A"; data: { + * field: string, + * } | { + * bruh: string, + * } }} A + * @property {{ type: "B"; data: { + * other: number, + * } }} B + * + * @typedef {{ type: "A"; data: { + * field: string, + * } } | { type: "B"; data: { + * other: number, + * } }} AdjacentlyTaggedWithAlias_Serialize + * @property {{ type: "A"; data: { + * field: string, + * } }} A + * @property {{ type: "B"; data: { + * other: number, + * } }} B + * + * @typedef {{ + * b: number, + * }} B + * @property {number} b + * + * @typedef {"A" | "B"} BasicEnum + * @property {"A"} A + * @property {"B"} B + * + * @typedef {BoxedInner} BoxFlattened + * + * @typedef {{ + * c: { + * a: number, + * }, + * }} BoxInline + * @property {{ + * a: number, + * }} c + * + * @typedef {{ + * a: number, + * }} BoxedInner + * @property {number} a + * + * @typedef {string} BracedStruct + * @property {string} "0" + * + * @typedef {{ + * first: T, + * second: U, + * }} ChainedGenericDefault + * @property {T} first + * @property {U} second + * + * Some triple-slash comment + * Some more triple-slash comment + * + * @typedef { + * /** + * * Some triple-slash comment + * * Some more triple-slash comment + * */ + * ({ A: number }) & { B?: never } | + * /** + * * Some triple-slash comment + * * Some more triple-slash comment + * */ + * ({ B: { + * /** + * * Some triple-slash comment + * * Some more triple-slash comment + * */ + * a: number, + * } }) & { A?: never }} CommentedEnum + * @property { + * /** + * * Some triple-slash comment + * * Some more triple-slash comment + * */ + * { A: number }} A - Some triple-slash comment Some more triple-slash comment + * @property { + * /** + * * Some triple-slash comment + * * Some more triple-slash comment + * */ + * { B: { + * /** + * * Some triple-slash comment + * * Some more triple-slash comment + * */ + * a: number, + * } }} B - Some triple-slash comment Some more triple-slash comment + * + * Some triple-slash comment + * Some more triple-slash comment + * + * @typedef {{ + * /** + * * Some triple-slash comment + * * Some more triple-slash comment + * */ + * a: number, + * }} CommentedStruct + * @property {number} a - Some triple-slash comment Some more triple-slash comment + * + * @typedef {{ + * data: number[], + * a: number[], + * d: [number, number], + * }} ConstGenericInConstContainer + * @property {number[]} data + * @property {number[]} a + * @property {[number, number]} d + * + * @typedef {{ + * data: [number], + * a: [number, number], + * d: [number, number], + * }} ConstGenericInNonConstContainer + * @property {[number]} data + * @property {[number, number]} a + * @property {[number, number]} d + * + * @typedef {{ + * foo: Generic1, + * bar: Generic1[], + * baz: { [key in string]: Generic1 }, + * }} Container1 + * @property {Generic1} foo + * @property {Generic1[]} bar + * @property {{ [key in string]: Generic1 }} baz + * + * @typedef {string} ContainerTypeOverrideEnum + * + * @typedef {string} ContainerTypeOverrideGeneric + * + * @typedef {string} ContainerTypeOverrideStruct + * + * @typedef {T} ContainerTypeOverrideToGeneric + * + * @typedef {[string, number]} ContainerTypeOverrideTuple + * + * @typedef {[T, string]} ContainerTypeOverrideTupleGeneric + * + * @typedef {{ + * flattened: number, + * }} D + * @property {number} flattened + * + * @typedef {{ + * a: A, + * b: B, + * }} Demo + * @property {A} a + * @property {B} b + * + * @typedef { + * /** + * * @deprecated + * */ + * "A" | + * /** + * * @deprecated Nope + * */ + * "B" | + * /** + * * @deprecated Nope + * */ + * "C"} DeprecatedEnumVariants + * @property { + * /** + * * @deprecated + * */ + * "A"} A - @deprecated + * @property { + * /** + * * @deprecated Nope + * */ + * "B"} B - @deprecated Nope + * @property { + * /** + * * @deprecated Nope + * */ + * "C"} C - @deprecated Nope + * + * @typedef {{ + * a: number, + * /** + * * @deprecated + * */ + * b: string, + * /** + * * @deprecated This field is cringe! + * */ + * c: string, + * /** + * * @deprecated This field is cringe! + * */ + * d: string, + * }} DeprecatedFields + * @property {number} a + * @property {string} b - @deprecated + * @property {string} c - @deprecated This field is cringe! + * @property {string} d - @deprecated This field is cringe! + * + * @typedef {[ + * /** + * * @deprecated + * */ + * string, + * /** + * * @deprecated Nope + * */ + * string, + * /** + * * @deprecated Nope + * */ + * number]} DeprecatedTupleVariant + * @property {string} "0" - @deprecated + * @property {string} "1" - @deprecated Nope + * @property {number} "2" - @deprecated Nope + * + * @deprecated + * @typedef {{ + * a: number, + * }} DeprecatedType + * @property {number} a + * + * @deprecated Look at you big man using a deprecation message + * @typedef {{ + * a: number, + * }} DeprecatedTypeWithMsg + * @property {number} a + * + * @deprecated Look at you big man using a deprecation message + * @typedef {{ + * a: number, + * }} DeprecatedTypeWithMsg2 + * @property {number} a + * + * @typedef {{ + * a: ToBeFlattened, + * b: ToBeFlattened, + * }} DoubleFlattened + * @property {ToBeFlattened} a + * @property {ToBeFlattened} b + * + * @typedef {{ A: string } | "B"} Eight + * @property {{ A: string }} A + * @property {"B"} B + * + * @typedef {never} EmptyEnum + * + * @typedef {never} EmptyEnumTagged + * + * @typedef {never} EmptyEnumTaggedWContent + * + * @typedef {never} EmptyEnumUntagged + * + * @typedef {Record} EmptyStruct + * + * @typedef {{ + * a: "EmptyStructWithTag", + * }} EmptyStructWithTag + * @property {"EmptyStructWithTag"} a + * + * @typedef {{ t: "A" } | { t: "B" }} Enum + * @property {{ t: "A" }} A + * @property {{ t: "B" }} B + * + * @typedef {{ t: "C" } | { t: "B" } | { t: "D"; enumField: null }} Enum2 + * @property {{ t: "C" }} C + * @property {{ t: "B" }} B + * @property {{ t: "D"; enumField: null }} D + * + * @typedef {{ t: "A"; b: string }} Enum3 + * @property {{ t: "A"; b: string }} A + * + * @typedef {({ A: string }) & { D?: never; bbb?: never; cccc?: never } | ({ bbb: number }) & { A?: never; D?: never; cccc?: never } | ({ cccc: number }) & { A?: never; D?: never; bbb?: never } | ({ D: { + * a: string, + * bbbbbb: number, + * } }) & { A?: never; bbb?: never; cccc?: never }} EnumMacroAttributes + * @property {{ A: string }} A + * @property {{ bbb: number }} bbb + * @property {{ cccc: number }} cccc + * @property {{ D: { + * a: string, + * bbbbbb: number, + * } }} D + * + * @typedef {{ + * a: Partial<{ [key in BasicEnum]: number }>, + * }} EnumReferenceRecordKey + * @property {Partial<{ [key in BasicEnum]: number }>} a + * + * @typedef {"HELLOWORLD" | "VARIANTB" | "TESTINGWORDS"} EnumRenameAllUppercase + * @property {"HELLOWORLD"} HELLOWORLD + * @property {"VARIANTB"} VARIANTB + * @property {"TESTINGWORDS"} TESTINGWORDS + * + * @typedef {EnumWithMultipleVariantAliases_Serialize | EnumWithMultipleVariantAliases_Deserialize} EnumWithMultipleVariantAliases + * @property {EnumWithMultipleVariantAliases_Serialize} Serialize + * @property {EnumWithMultipleVariantAliases_Deserialize} Deserialize + * + * @typedef {"Variant" | "bruh" | "alternative" | "Other"} EnumWithMultipleVariantAliases_Deserialize + * @property {"Variant"} Variant + * @property {"bruh"} bruh + * @property {"alternative"} alternative + * @property {"Other"} Other + * + * @typedef {"Variant" | "Other"} EnumWithMultipleVariantAliases_Serialize + * @property {"Variant"} Variant + * @property {"Other"} Other + * + * @typedef {EnumWithVariantAlias_Serialize | EnumWithVariantAlias_Deserialize} EnumWithVariantAlias + * @property {EnumWithVariantAlias_Serialize} Serialize + * @property {EnumWithVariantAlias_Deserialize} Deserialize + * + * @typedef {EnumWithVariantAliasAndRename_Serialize | EnumWithVariantAliasAndRename_Deserialize} EnumWithVariantAliasAndRename + * @property {EnumWithVariantAliasAndRename_Serialize} Serialize + * @property {EnumWithVariantAliasAndRename_Deserialize} Deserialize + * + * @typedef {"renamed_variant" | "bruh" | "Other"} EnumWithVariantAliasAndRename_Deserialize + * @property {"renamed_variant"} renamed_variant + * @property {"bruh"} bruh + * @property {"Other"} Other + * + * @typedef {"renamed_variant" | "Other"} EnumWithVariantAliasAndRename_Serialize + * @property {"renamed_variant"} renamed_variant + * @property {"Other"} Other + * + * @typedef {"Variant" | "bruh" | "Other"} EnumWithVariantAlias_Deserialize + * @property {"Variant"} Variant + * @property {"bruh"} bruh + * @property {"Other"} Other + * + * @typedef {"Variant" | "Other"} EnumWithVariantAlias_Serialize + * @property {"Variant"} Variant + * @property {"Other"} Other + * + * @typedef {"A" | ({ B: { + * id: string, + * method: string, + * } }) & { C?: never } | ({ C: string }) & { B?: never }} ExternallyTagged + * @property {"A"} A + * @property {{ B: { + * id: string, + * method: string, + * } }} B + * @property {{ C: string }} C + * + * @typedef {{ A: string }} ExtraBracketsInTupleVariant + * @property {{ A: string }} A + * + * @typedef {string} ExtraBracketsInUnnamedStruct + * @property {string} "0" + * + * @typedef {{ + * a: string, + * }} First + * @property {string} a + * + * @typedef {{ + * a: number, + * b: number, + * }} FlattenA + * @property {number} a + * @property {number} b + * + * @typedef {{ + * c: number, + * } & FlattenA} FlattenB + * @property {number} c + * + * @typedef {{ + * c: number, + * } & FlattenA} FlattenC + * @property {number} c + * + * @typedef {{ + * a: FlattenA, + * c: number, + * }} FlattenD + * @property {FlattenA} a + * @property {number} c + * + * @typedef {{ + * b: ({ + * c: number, + * }) & (FlattenA), + * d: number, + * }} FlattenE + * @property {({ + * c: number, + * }) & (FlattenA)} b + * @property {number} d + * + * @typedef {{ tag: "One" } | { tag: "Two" } | { tag: "Three" }} FlattenEnum + * @property {{ tag: "One" }} One + * @property {{ tag: "Two" }} Two + * @property {{ tag: "Three" }} Three + * + * @typedef {{ + * outer: string, + * } & FlattenEnum} FlattenEnumStruct + * @property {string} outer + * + * @typedef {{ + * b: ({ + * c: number, + * }) & (FlattenA), + * d: number, + * }} FlattenF + * @property {({ + * c: number, + * }) & (FlattenA)} b + * @property {number} d + * + * @typedef {{ + * b: FlattenB, + * d: number, + * }} FlattenG + * @property {FlattenB} b + * @property {number} d + * + * @typedef {{ + * id: string, + * } & NestedEnum} FlattenOnNestedEnum + * @property {string} id + * + * @typedef {Inner} FlattenedInner + * + * @typedef {{ + * a: First, + * b: { + * a: string, + * }, + * }} Fourth + * @property {First} a + * @property {{ + * a: string, + * }} b + * + * @typedef {{ + * value: T, + * values: T[], + * }} Generic1 + * @property {T} value + * @property {T[]} values + * + * @typedef {({ A: A }) & { B?: never; C?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ B: [B, B, B] }) & { A?: never; C?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ C: C[] }) & { A?: never; B?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ D: A[][][] }) & { A?: never; B?: never; C?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ E: { + * a: A, + * b: B, + * c: C, + * } }) & { A?: never; B?: never; C?: never; D?: never; X?: never; Y?: never; Z?: never } | ({ X: number[] }) & { A?: never; B?: never; C?: never; D?: never; E?: never; Y?: never; Z?: never } | ({ Y: number }) & { A?: never; B?: never; C?: never; D?: never; E?: never; X?: never; Z?: never } | ({ Z: number[][] }) & { A?: never; B?: never; C?: never; D?: never; E?: never; X?: never; Y?: never }} Generic2 + * @property {{ A: A }} A + * @property {{ B: [B, B, B] }} B + * @property {{ C: C[] }} C + * @property {{ D: A[][][] }} D + * @property {{ E: { + * a: A, + * b: B, + * c: C, + * } }} E + * @property {{ X: number[] }} X + * @property {{ Y: number }} Y + * @property {{ Z: number[][] }} Z + * + * @typedef {{ + * value: T, + * values: T[], + * }} GenericAutoBound + * @property {T} value + * @property {T[]} values + * + * @typedef {{ + * value: T, + * values: T[], + * }} GenericAutoBound2 + * @property {T} value + * @property {T[]} values + * + * @typedef {{ + * value: T, + * }} GenericDefault + * @property {T} value + * + * @typedef {{ + * value: T, + * }} GenericDefaultSkipped + * @property {T} value + * + * @typedef {{ + * value: number, + * }} GenericDefaultSkippedNonType + * @property {number} value + * + * @typedef {{ + * generic_flattened: T, + * }} GenericFlattened + * @property {T} generic_flattened + * + * @typedef {T[][]} GenericNewType1 + * @property {T[][]} "0" + * + * @typedef {{ + * pair: Pair, + * }} GenericParameterOrderPreserved + * @property {Pair} pair + * + * @typedef {{ + * arg: T, + * }} GenericStruct + * @property {T} arg + * + * @typedef {{ + * a: T, + * b: [T, T], + * c: [T, [T, T]], + * d: [T, T, T], + * e: [([T, T]), ([T, T]), ([T, T])], + * f: T[], + * g: T[][], + * h: ([([T, T]), ([T, T]), ([T, T])])[], + * }} GenericStruct2 + * @property {T} a + * @property {[T, T]} b + * @property {[T, [T, T]]} c + * @property {[T, T, T]} d + * @property {[([T, T]), ([T, T]), ([T, T])]} e + * @property {T[]} f + * @property {T[][]} g + * @property {([([T, T]), ([T, T]), ([T, T])])[]} h + * + * @typedef {[T, T[], T[][]]} GenericTuple + * @property {T} "0" + * @property {T[]} "1" + * @property {T[][]} "2" + * + * @typedef {T} GenericTupleStruct + * @property {T} "0" + * + * @typedef {"Undefined" | T} GenericType + * @property {"Undefined"} Undefined + * @property {T} Value + * + * @typedef {{ [key in number]: string }} HasGenericAlias + * @property {{ [key in number]: string }} "0" + * + * @typedef {{ + * b: { + * data: [number, number], + * a: [number, number], + * d: [number, number, number], + * }, + * c: { + * data: [number, number, number], + * a: [number, number], + * d: [number, number, number], + * }, + * d: [number, number], + * }} InlineConstGenericContainer + * @property {{ + * data: [number, number], + * a: [number, number], + * d: [number, number, number], + * }} b + * @property {{ + * data: [number, number, number], + * a: [number, number], + * d: [number, number, number], + * }} c + * @property {[number, number]} d + * + * @typedef {{ A: { + * a: string, + * } }} InlineEnumField + * @property {{ A: { + * a: string, + * } }} A + * + * @typedef {{ + * g: InlineFlattenGenericsG, + * gi: { + * t: string, + * }, + * } & InlineFlattenGenericsG} InlineFlattenGenerics + * @property {InlineFlattenGenericsG} g + * @property {{ + * t: string, + * }} gi + * + * @typedef {{ + * t: T, + * }} InlineFlattenGenericsG + * @property {T} t + * + * @typedef {{ + * optional_field: { + * a: string, + * } | null, + * }} InlineOptionalType + * @property {{ + * a: string, + * } | null} optional_field + * + * @typedef {{ + * data: number[], + * a: number[], + * d: [number, number, number], + * e: InlineRecursiveConstGeneric, + * }} InlineRecursiveConstGeneric + * @property {number[]} data + * @property {number[]} a + * @property {[number, number, number]} d + * @property {InlineRecursiveConstGeneric} e + * + * @typedef {{ + * b: { + * data: [number, number], + * a: [number, number], + * d: [number, number, number], + * e: InlineRecursiveConstGeneric, + * }, + * c: { + * data: [number, number, number], + * a: [number, number], + * d: [number, number, number], + * e: InlineRecursiveConstGeneric, + * }, + * d: [number, number], + * }} InlineRecursiveConstGenericContainer + * @property {{ + * data: [number, number], + * a: [number, number], + * d: [number, number, number], + * e: InlineRecursiveConstGeneric, + * }} b + * @property {{ + * data: [number, number, number], + * a: [number, number], + * d: [number, number, number], + * e: InlineRecursiveConstGeneric, + * }} c + * @property {[number, number]} d + * + * @typedef {{ + * ref_struct: SimpleStruct, + * val: number, + * }} InlineStruct + * @property {SimpleStruct} ref_struct + * @property {number} val + * + * @typedef {{ + * demo: [string, boolean], + * }} InlineTuple + * @property {[string, boolean]} demo + * + * @typedef {{ + * demo: [{ + * demo: [string, boolean], + * }, boolean], + * }} InlineTuple2 + * @property {[{ + * demo: [string, boolean], + * }, boolean]} demo + * + * @typedef {{ + * inline_this: { + * ref_struct: SimpleStruct, + * val: number, + * }, + * dont_inline_this: RefStruct, + * }} InlinerStruct + * @property {{ + * ref_struct: SimpleStruct, + * val: number, + * }} inline_this + * @property {RefStruct} dont_inline_this + * + * @typedef {{ + * a: number, + * } & FlattenedInner} Inner + * @property {number} a + * + * @typedef {{ + * type: "A", + * } & { [key in string]: string }} InternallyTaggedD + * @property {{ + * type: "A", + * } & { [key in string]: string }} A + * + * @typedef {{ type: "A" }} InternallyTaggedE + * @property {{ type: "A" }} A + * + * @typedef {{ type: "A" }} InternallyTaggedF + * @property {{ type: "A" }} A + * + * @typedef {null} InternallyTaggedFInner + * @property {null} A + * + * @typedef {{ type: "A" }} InternallyTaggedH + * @property {{ type: "A" }} A + * + * @typedef {null} InternallyTaggedHInner + * @property {null} "0" + * + * @typedef {{ + * type: "A", + * } & { type: "A" } | { type: "B" }} InternallyTaggedL + * @property {{ + * type: "A", + * } & { type: "A" } | { type: "B" }} A + * + * @typedef {{ type: "A" } | { type: "B" }} InternallyTaggedLInner + * @property {{ type: "A" }} A + * @property {{ type: "B" }} B + * + * @typedef {{ type: "A" }} InternallyTaggedM + * @property {{ type: "A" }} A + * + * @typedef {"A" | "B"} InternallyTaggedMInner + * @property {"A"} A + * @property {"B"} B + * + * @typedef {InternallyTaggedWithAlias_Serialize | InternallyTaggedWithAlias_Deserialize} InternallyTaggedWithAlias + * @property {InternallyTaggedWithAlias_Serialize} Serialize + * @property {InternallyTaggedWithAlias_Deserialize} Deserialize + * + * @typedef {{ + * type: "A", + * } & { + * field: string, + * } | { + * bruh: string, + * } | { type: "B"; other: number }} InternallyTaggedWithAlias_Deserialize + * @property {{ + * type: "A", + * } & { + * field: string, + * } | { + * bruh: string, + * }} A + * @property {{ type: "B"; other: number }} B + * + * @typedef {({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }} InternallyTaggedWithAlias_Serialize + * @property {{ type: "A"; field: string }} A + * @property {{ type: "B"; other: number }} B + * + * @typedef {{ + * cause: null, + * }} InvalidToValidType + * @property {null} cause + * + * @typedef {({ A: { + * a: string, + * } }) & { B?: never } | ({ B: { + * b: string, + * } }) & { A?: never }} Issue221External + * @property {{ A: { + * a: string, + * } }} A + * @property {{ B: { + * b: string, + * } }} B + * + * @typedef {({ a: string }) & { b?: never; values?: never } | ({ b: string }) & { a?: never; values?: never } | ({ values: { [key in string]: string } }) & { a?: never; b?: never }} Issue221UntaggedMixed + * @property {{ a: string }} A + * @property {{ b: string }} B + * @property {{ values: { [key in string]: string } }} Unsafe + * + * @typedef {({ a: string }) & { b?: never } | ({ b: string }) & { a?: never }} Issue221UntaggedSafe + * @property {{ a: string }} A + * @property {{ b: string }} B + * + * @typedef {{ + * default_unity_arguments: string[], + * }} Issue281 + * @property {string[]} default_unity_arguments + * + * https://github.com/specta-rs/specta/issues/374 + * + * @typedef {Issue374_Serialize | Issue374_Deserialize} Issue374 + * @property {Issue374_Serialize} Serialize + * @property {Issue374_Deserialize} Deserialize + * + * https://github.com/specta-rs/specta/issues/374 + * + * @typedef {{ + * foo?: boolean, + * bar?: boolean, + * }} Issue374_Deserialize + * @property {boolean} [foo] + * @property {boolean} [bar] + * + * https://github.com/specta-rs/specta/issues/374 + * + * @typedef {{ + * foo?: boolean, + * bar?: boolean, + * }} Issue374_Serialize + * @property {boolean} [foo] + * @property {boolean} [bar] + * + * @typedef {{ + * "test-ing": string, + * }} KebabCase + * @property {string} "test-ing" + * + * @typedef {({ Borrowed: T }) & { Owned?: never } | ({ Owned: T }) & { Borrowed?: never }} LifetimeGenericEnum + * @property {{ Borrowed: T }} Borrowed + * @property {{ Owned: T }} Owned + * + * @typedef {{ + * borrowed: T[], + * owned: T[], + * }} LifetimeGenericStruct + * @property {T[]} borrowed + * @property {T[]} owned + * + * @typedef {{ event: "started"; data: { + * projectName: string, + * } } | { event: "progressTest"; data: { + * projectName: string, + * status: string, + * progress: number, + * } } | { event: "finished"; data: { + * projectName: string, + * } }} LoadProjectEvent + * @property {{ event: "started"; data: { + * projectName: string, + * } }} started + * @property {{ event: "progressTest"; data: { + * projectName: string, + * status: string, + * progress: number, + * } }} progressTest + * @property {{ event: "finished"; data: { + * projectName: string, + * } }} finished + * + * @typedef {({ Demo: string }) & { Demo2?: never } | ({ Demo2: { + * demo2: string, + * } }) & { Demo?: never }} MacroEnum + * @property {{ Demo: string }} Demo + * @property {{ Demo2: { + * demo2: string, + * } }} Demo2 + * + * @typedef {string} MacroStruct + * @property {string} "0" + * + * @typedef {{ + * demo: string, + * }} MacroStruct2 + * @property {string} demo + * + * @typedef {T} MaybeValidKey + * @property {T} "0" + * + * @typedef {Record} MyEmptyInput + * + * @typedef {({ A: string }) & { B?: never } | ({ B: number }) & { A?: never }} MyEnum + * @property {{ A: string }} A + * @property {{ B: number }} B + * + * @typedef {{ t: "Variant"; c: { + * inner: First, + * } }} MyEnumAdjacent + * @property {{ t: "Variant"; c: { + * inner: First, + * } }} Variant + * + * @typedef {{ Variant: { + * inner: First, + * } }} MyEnumExternal + * @property {{ Variant: { + * inner: First, + * } }} Variant + * + * @typedef {{ + * type: "Variant", + * } & First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & First} Variant + * + * @typedef {{ inner: First }} MyEnumUntagged + * @property {{ inner: First }} Variant + * + * @typedef {{ + * data: number[], + * a: number[], + * d: [number, number], + * }} NamedConstGeneric + * @property {number[]} data + * @property {number[]} a + * @property {[number, number]} d + * + * @typedef {{ + * a: NamedConstGeneric, + * b: NamedConstGeneric, + * d: [number, number], + * }} NamedConstGenericContainer + * @property {NamedConstGeneric} a + * @property {NamedConstGeneric} b + * @property {[number, number]} d + * + * @typedef {{ type: "a"; value: string } | { type: "b"; value: number }} NestedEnum + * @property {{ type: "a"; value: string }} a + * @property {{ type: "b"; value: number }} b + * + * @typedef {{ t: "A"; c: string } | { t: "B" } | { t: "C"; c: { + * a: string, + * } } | { t: "D"; c: First }} Ninth + * @property {{ t: "A"; c: string }} A + * @property {{ t: "B" }} B + * @property {{ t: "C"; c: { + * a: string, + * } }} C + * @property {{ t: "D"; c: First }} D + * + * @typedef {string | null} NonOptional + * @property {string | null} "0" + * + * @typedef {Optional_Serialize | Optional_Deserialize} Optional + * @property {Optional_Serialize} Serialize + * @property {Optional_Deserialize} Deserialize + * + * @typedef {({ A?: string | null }) & { B?: never; C?: never } | ({ B: { + * a: string | null, + * } }) & { A?: never; C?: never } | ({ C: { + * a?: string | null, + * } }) & { A?: never; B?: never }} OptionalInEnum + * @property {{ A?: string | null }} A + * @property {{ B: { + * a: string | null, + * } }} B + * @property {{ C: { + * a?: string | null, + * } }} C + * + * @typedef {string | null} OptionalOnNamedField + * @property {string | null} ["0"] + * + * @typedef {{ + * b: string | null, + * }} OptionalOnTransparentNamedField + * @property {string | null} b + * + * @typedef {{ + * a: number | null, + * b?: number | null, + * c: string | null, + * d?: boolean, + * }} Optional_Deserialize + * @property {number | null} a + * @property {number | null} [b] + * @property {string | null} c + * @property {boolean} [d] + * + * @typedef {{ + * a: number | null, + * b?: number | null, + * c?: string, + * d: boolean, + * }} Optional_Serialize + * @property {number | null} a + * @property {number | null} [b] + * @property {string} [c] + * @property {boolean} d + * + * @typedef {{ + * overriden_field: string, + * }} OverridenStruct + * @property {string} overriden_field + * + * @typedef {{ + * first: Z, + * second: A, + * }} Pair + * @property {Z} first + * @property {A} second + * + * @typedef {{ + * a: string, + * }} PlaceholderInnerField + * @property {string} a + * + * @typedef {{ + * demo: Recursive, + * }} Recursive + * @property {Recursive} demo + * + * @typedef {{ A: { + * demo: RecursiveInEnum, + * } }} RecursiveInEnum + * @property {{ A: { + * demo: RecursiveInEnum, + * } }} A + * + * @typedef {RecursiveInline} RecursiveInline + * + * @typedef {{ + * demo: { [key in string]: RecursiveMapValue }, + * }} RecursiveMapValue + * @property {{ [key in string]: RecursiveMapValue }} demo + * + * @typedef {RecursiveInline} RecursiveTransparent + * @property {RecursiveInline} "0" + * + * @typedef {TestEnum} RefStruct + * @property {TestEnum} "0" + * + * @typedef {{ [key in string]: null }} Regular + * @property {{ [key in string]: null }} "0" + * + * @typedef {"OneWord" | "Two words"} Rename + * @property {"OneWord"} OneWord + * @property {"Two words"} "Two words" + * + * @typedef {{ + * "a/b": number, + * }} RenameSerdeSpecialChar + * @property {number} "a/b" + * + * @typedef {{ + * "@odata.context": string, + * }} RenameWithWeirdCharsField + * @property {string} "@odata.context" + * + * @typedef {{ "@odata.context": string }} RenameWithWeirdCharsVariant + * @property {{ "@odata.context": string }} "@odata.context" + * + * @typedef {{ + * "": string, + * "a\"b": string, + * "a\\b": string, + * "line\nbreak": string, + * "line\u2028break": string, + * "line\u2029break": string, + * }} RenamedFieldKeys + * @property {string} "" + * @property {string} "a\"b" + * @property {string} "a\\b" + * @property {string} "line\nbreak" + * @property {string} "line\u2028break" + * @property {string} "line\u2029break" + * + * @typedef {"a-b"} RenamedVariantWithSkippedPayload + * @property {"a-b"} "a-b" + * + * @typedef {{ + * a: number, + * }} Second + * @property {number} a + * + * @typedef {{ + * a: First, + * b: Second, + * }} Seventh + * @property {First} a + * @property {Second} b + * + * @typedef {{ + * a: number, + * b: string, + * c: [number, string, number], + * d: string[], + * e: string | null, + * }} SimpleStruct + * @property {number} a + * @property {string} b + * @property {[number, string, number]} c + * @property {string[]} d + * @property {string | null} e + * + * Some single-line comment + * + * @typedef { + * /** Some single-line comment */ + * ({ A: number }) & { B?: never } | + * /** Some single-line comment */ + * ({ B: { + * /** Some single-line comment */ + * a: number, + * } }) & { A?: never }} SingleLineComment + * @property { + * /** Some single-line comment */ + * { A: number }} A - Some single-line comment + * @property { + * /** Some single-line comment */ + * { B: { + * /** Some single-line comment */ + * a: number, + * } }} B - Some single-line comment + * + * @typedef {{ + * a: First, + * b: First, + * }} Sixth + * @property {First} a + * @property {First} b + * + * @typedef {{ + * b: number, + * }} SkipField + * @property {number} b + * + * @typedef {({ A: Record }) & { B?: never } | ({ B: { + * b: number, + * } }) & { A?: never }} SkipNamedFieldInVariant + * @property {{ A: Record }} A + * @property {{ B: { + * b: number, + * } }} B + * + * @typedef {Record} SkipOnlyField + * + * @typedef {{ + * a: number, + * }} SkipStructFields + * @property {number} a + * + * @typedef {"A" | { B: [number] }} SkipUnnamedFieldInVariant + * @property {"A"} A + * @property {{ B: [number] }} B + * + * @typedef {{ A: string }} SkipVariant + * @property {{ A: string }} A + * + * @typedef {{ tag: "A"; data: string }} SkipVariant2 + * @property {{ tag: "A"; data: string }} A + * + * @typedef {{ A: { + * a: string, + * } }} SkipVariant3 + * @property {{ A: { + * a: string, + * } }} A + * + * @typedef {{ type: "A" } | { type: "B"; data: string }} SkippedFieldWithinVariant + * @property {{ type: "A" }} A + * @property {{ type: "B"; data: string }} B + * + * @typedef {{ + * a: number, + * }} SpectaSkipNonTypeField + * @property {number} a + * + * @typedef {{ + * string_ident: string, + * u32_ident: number, + * path: string, + * tuple: [string, number], + * }} SpectaTypeOverride + * @property {string} string_ident + * @property {number} u32_ident + * @property {string} path + * @property {[string, number]} tuple + * + * @typedef {{ + * b: string, + * }} Struct2 + * @property {string} b + * + * @typedef {{ + * t: "StructNew", + * a: string, + * }} StructNew + * @property {"StructNew"} t + * @property {string} a + * + * @typedef {StructPhaseSpecificRenameSerialize | StructPhaseSpecificRenameDeserialize} StructPhaseSpecificRename + * @property {StructPhaseSpecificRenameSerialize} Serialize + * @property {StructPhaseSpecificRenameDeserialize} Deserialize + * + * @typedef {{ + * kind: "StructPhaseSpecificRenameDeserialize", + * der: string, + * }} StructPhaseSpecificRenameDeserialize + * @property {"StructPhaseSpecificRenameDeserialize"} kind + * @property {string} der + * + * @typedef {{ + * kind: "StructPhaseSpecificRenameSerialize", + * ser: string, + * }} StructPhaseSpecificRenameSerialize + * @property {"StructPhaseSpecificRenameSerialize"} kind + * @property {string} ser + * + * @typedef {{ + * A: number, + * B: number, + * }} StructRenameAllUppercase + * @property {number} A + * @property {number} B + * + * @typedef {StructWithAlias_Serialize | StructWithAlias_Deserialize} StructWithAlias + * @property {StructWithAlias_Serialize} Serialize + * @property {StructWithAlias_Deserialize} Deserialize + * + * @typedef {StructWithAliasAndRename_Serialize | StructWithAliasAndRename_Deserialize} StructWithAliasAndRename + * @property {StructWithAliasAndRename_Serialize} Serialize + * @property {StructWithAliasAndRename_Deserialize} Deserialize + * + * @typedef {{ + * renamed_field: string, + * }} StructWithAliasAndRename_Deserialize + * @property {{ + * renamed_field: string, + * }} "" + * @property {{ + * renamed_field: string, + * }} "" + * + * @typedef {{ + * renamed_field: string, + * }} StructWithAliasAndRename_Serialize + * @property {string} renamed_field + * + * @typedef {{ + * field: string, + * } | { + * bruh: string, + * }} StructWithAlias_Deserialize + * @property {{ + * field: string, + * } | { + * bruh: string, + * }} "" + * @property {{ + * field: string, + * } | { + * bruh: string, + * }} "" + * + * @typedef {{ + * field: string, + * }} StructWithAlias_Serialize + * @property {string} field + * + * @typedef {StructWithMultipleAliases_Serialize | StructWithMultipleAliases_Deserialize} StructWithMultipleAliases + * @property {StructWithMultipleAliases_Serialize} Serialize + * @property {StructWithMultipleAliases_Deserialize} Deserialize + * + * @typedef {{ + * field: string, + * } | { + * bruh: string, + * } | { + * alternative: string, + * } | { + * another: string, + * }} StructWithMultipleAliases_Deserialize + * @property {{ + * field: string, + * } | { + * bruh: string, + * } | { + * alternative: string, + * } | { + * another: string, + * }} "" + * @property {{ + * field: string, + * } | { + * bruh: string, + * } | { + * alternative: string, + * } | { + * another: string, + * }} "" + * @property {{ + * field: string, + * } | { + * bruh: string, + * } | { + * alternative: string, + * } | { + * another: string, + * }} "" + * @property {{ + * field: string, + * } | { + * bruh: string, + * } | { + * alternative: string, + * } | { + * another: string, + * }} "" + * + * @typedef {{ + * field: string, + * }} StructWithMultipleAliases_Serialize + * @property {string} field + * + * @typedef {{ + * type: "TagOnStructWithInline", + * a: First, + * b: { + * a: string, + * }, + * }} TagOnStructWithInline + * @property {"TagOnStructWithInline"} type + * @property {First} a + * @property {{ + * a: string, + * }} b + * + * @typedef {string | "B" | { + * a: string, + * } | First} Tenth + * @property {string} A + * @property {"B"} B + * @property {{ + * a: string, + * }} C + * @property {First} D + * + * @typedef {never} TestCollectionRegister + * + * @typedef {"Unit" | ({ Single: number }) & { Multiple?: never; Struct?: never } | ({ Multiple: [number, number] }) & { Single?: never; Struct?: never } | ({ Struct: { + * a: number, + * } }) & { Multiple?: never; Single?: never }} TestEnum + * @property {"Unit"} Unit + * @property {{ Single: number }} Single + * @property {{ Multiple: [number, number] }} Multiple + * @property {{ Struct: { + * a: number, + * } }} Struct + * + * @typedef {{ + * b: { [key in string]: string }, + * c: First, + * } & First} Third + * @property {{ [key in string]: string }} b + * @property {First} c + * + * @typedef {{ + * a: string, + * }} ToBeFlattened + * @property {string} a + * + * @typedef {string} TransparentStruct + * @property {string} "0" + * + * @typedef {TransparentTypeInner} TransparentType + * @property {TransparentTypeInner} "0" + * + * @typedef {null} TransparentType2 + * @property {null} "0" + * + * @typedef {{ + * inner: string, + * }} TransparentTypeInner + * @property {string} inner + * + * @typedef {string} TransparentTypeWithOverride + * @property {string} "0" + * + * @typedef {null} TransparentWithSkip + * @property {null} "0" + * + * @typedef {string} TransparentWithSkip2 + * @property {string} "0" + * + * @typedef {string} TransparentWithSkip3 + * @property {string} "0" + * + * @typedef {[number[], [number[], number[]], [number[], number[], number[]]]} TupleNested + * @property {number[]} "0" + * @property {[number[], number[]]} "1" + * @property {[number[], number[], number[]]} "2" + * + * @typedef {string} TupleStruct + * @property {string} "0" + * + * @typedef {number} TupleStruct1 + * @property {number} "0" + * + * @typedef {[number, boolean, string]} TupleStruct3 + * @property {number} "0" + * @property {boolean} "1" + * @property {string} "2" + * + * @typedef {string} TupleStructWithRep + * @property {string} "0" + * + * @typedef {null} Unit1 + * + * @typedef {Record} Unit2 + * + * @typedef {[]} Unit3 + * + * @typedef {null} Unit4 + * @property {null} "0" + * + * @typedef {"A"} Unit5 + * @property {"A"} A + * + * @typedef {{ A: null }} Unit6 + * @property {{ A: null }} A + * + * @typedef {{ A: Record }} Unit7 + * @property {{ A: Record }} A + * + * @typedef {"A" | "B" | "C"} UnitVariants + * @property {"A"} A + * @property {"B"} B + * @property {"C"} C + * + * @typedef {string | number | { id: string } | [string, boolean]} UntaggedVariants + * @property {string} A + * @property {number} B + * @property {number} C + * @property {{ id: string }} D + * @property {[string, boolean]} E + * + * @typedef {string | number} UntaggedVariantsKey + * @property {string} A + * @property {number} B + * @property {number} C + * + * @typedef {null | number} UntaggedVariantsWithDuplicateBranches + * @property {null} A + * @property {number} B + * @property {null} C + * + * @typedef {string | [number, string] | number} UntaggedVariantsWithoutValue + * @property {string} A + * @property {[number, string]} B + * @property {number} C + * + * @typedef {UntaggedWithAlias_Serialize | UntaggedWithAlias_Deserialize} UntaggedWithAlias + * @property {UntaggedWithAlias_Serialize} Serialize + * @property {UntaggedWithAlias_Deserialize} Deserialize + * + * @typedef {{ + * field: string, + * } | { + * bruh: string, + * } | { other: number }} UntaggedWithAlias_Deserialize + * @property {{ + * field: string, + * } | { + * bruh: string, + * }} A + * @property {{ other: number }} B + * + * @typedef {({ field: string }) & { other?: never } | ({ other: number }) & { field?: never }} UntaggedWithAlias_Serialize + * @property {{ field: string }} A + * @property {{ other: number }} B + * + * @typedef {{ [key in MaybeValidKey]: null }} ValidMaybeValidKey + * @property {{ [key in MaybeValidKey]: null }} "0" + * + * @typedef {{ [key in MaybeValidKey>]: null }} ValidMaybeValidKeyNested + * @property {{ [key in MaybeValidKey>]: null }} "0" + */ + ════════════════════════════════════════ + +tests/ + tests/ + types.js (28223 bytes) + ──────────────────────────────────────── + // This file has been generated by Specta. Do not edit this file manually. + + /** + * @typedef {import("../../std/ops")} std$ops + * @typedef {import("../../std/result")} std$result + * @typedef {import("../../test/types")} test$types + * @typedef {import("../../test/types/type_type")} test$types$type_type + */ + /** + * @typedef {{ + * i8: number, + * i16: number, + * i32: number, + * u8: number, + * u16: number, + * u32: number, + * f32: number | null, + * f64: number | null, + * bool: boolean, + * char: string, + * "Range": std$ops.Range, + * "RangeInclusive": std$ops.RangeInclusive, + * "()": null, + * "(String, i32)": [string, number], + * "(String, i32, bool)": [string, number, boolean], + * "((String, i32), (bool, char, bool), ())": [[string, number], [boolean, string, boolean], null], + * "(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)": [boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean], + * "(Vec, Vec)": [number[], boolean[]], + * String: string, + * PathBuf: string, + * IpAddr: string, + * Ipv4Addr: string, + * Ipv6Addr: string, + * SocketAddr: string, + * SocketAddrV4: string, + * SocketAddrV6: string, + * "Cow<'static, str>": string, + * "Cow<'static, i32>": number, + * "&'static str": string, + * "&'static bool": boolean, + * "&'static i32": number, + * "Vec": number[], + * "&'static [i32]": number[], + * "&'static [i32; 3]": [number, number, number], + * "[i32; 3]": [number, number, number], + * "Vec": test$types.MyEnum[], + * "&'static [MyEnum]": test$types.MyEnum[], + * "&'static [MyEnum; 6]": [test$types.MyEnum, test$types.MyEnum, test$types.MyEnum, test$types.MyEnum, test$types.MyEnum, test$types.MyEnum], + * "[MyEnum; 2]": [test$types.MyEnum, test$types.MyEnum], + * "&'static [i32; 1]": [number], + * "&'static [i32; 0]": [], + * "Option": number | null, + * "Option<()>": null, + * "Option>": number[] | null, + * "Result": std$result.Result, + * "Vec>>": (number | null)[], + * "Option>>": number[] | null, + * "[Vec; 3]": [string[], string[], string[]], + * "Option>": string | null, + * "Option>>": string | null, + * "PhantomData<()>": null, + * "PhantomData": null, + * Infallible: never, + * Unit1: test$types.Unit1, + * Unit2: test$types.Unit2, + * Unit3: test$types.Unit3, + * Unit4: test$types.Unit4, + * Unit5: test$types.Unit5, + * Unit6: test$types.Unit6, + * Unit7: test$types.Unit7, + * SimpleStruct: test$types.SimpleStruct, + * TupleStruct1: test$types.TupleStruct1, + * TupleStruct3: test$types.TupleStruct3, + * TestEnum: test$types.TestEnum, + * RefStruct: test$types.RefStruct, + * InlinerStruct: test$types.InlinerStruct, + * "GenericStruct": test$types.GenericStruct, + * "GenericStruct": test$types.GenericStruct, + * FlattenEnumStruct: test$types.FlattenEnumStruct, + * OverridenStruct: test$types.OverridenStruct, + * HasGenericAlias: test$types.HasGenericAlias, + * EnumMacroAttributes: test$types.EnumMacroAttributes, + * InlineEnumField: test$types.InlineEnumField, + * InlineOptionalType: test$types.InlineOptionalType, + * Rename: test$types.Rename, + * TransparentType: test$types.TransparentType, + * TransparentType2: test$types.TransparentType2, + * TransparentTypeWithOverride: test$types.TransparentTypeWithOverride, + * "[Option; 3]": [(number | null), (number | null), (number | null)], + * "HashMap": Partial<{ [key in test$types.BasicEnum]: null }>, + * "HashMap": Partial<{ [key in test$types.BasicEnum]: number }>, + * "Option>>>": number | null, + * "Vec": test$types.PlaceholderInnerField[], + * EnumReferenceRecordKey: test$types.EnumReferenceRecordKey, + * FlattenOnNestedEnum: test$types.FlattenOnNestedEnum, + * MyEmptyInput: test$types.MyEmptyInput, + * "(String)": string, + * "(String,)": [string], + * ExtraBracketsInTupleVariant: test$types.ExtraBracketsInTupleVariant, + * ExtraBracketsInUnnamedStruct: test$types.ExtraBracketsInUnnamedStruct, + * "Vec": test$types.MyEnum[], + * InlineTuple: test$types.InlineTuple, + * InlineTuple2: test$types.InlineTuple2, + * "Box": string, + * "Box": string, + * SkippedFieldWithinVariant: test$types.SkippedFieldWithinVariant, + * KebabCase: test$types.KebabCase, + * "&[&str]": string[], + * "Issue281<'_>": test$types.Issue281, + * "LifetimeGenericStruct<'_, i32>": test$types.LifetimeGenericStruct, + * "LifetimeGenericEnum<'_, i32>": test$types.LifetimeGenericEnum, + * RenameWithWeirdCharsField: test$types.RenameWithWeirdCharsField, + * RenameWithWeirdCharsVariant: test$types.RenameWithWeirdCharsVariant, + * RenamedFieldKeys: test$types.RenamedFieldKeys, + * RenamedVariantWithSkippedPayload: test$types.RenamedVariantWithSkippedPayload, + * "type_type::Type": test$types$type_type.Type, + * ActualType: test$types.ActualType, + * SpectaTypeOverride: test$types.SpectaTypeOverride, + * ContainerTypeOverrideStruct: test$types.ContainerTypeOverrideStruct, + * ContainerTypeOverrideEnum: test$types.ContainerTypeOverrideEnum, + * "ContainerTypeOverrideGeneric>": test$types.ContainerTypeOverrideGeneric, + * "ContainerTypeOverrideToGeneric": test$types.ContainerTypeOverrideToGeneric, + * ContainerTypeOverrideTuple: test$types.ContainerTypeOverrideTuple, + * "ContainerTypeOverrideTupleGeneric": test$types.ContainerTypeOverrideTupleGeneric, + * InvalidToValidType: test$types.InvalidToValidType, + * TupleStruct: test$types.TupleStruct, + * TupleStructWithRep: test$types.TupleStructWithRep, + * "GenericTupleStruct": test$types.GenericTupleStruct, + * BracedStruct: test$types.BracedStruct, + * Struct: test$types.StructNew, + * Struct2: test$types.Struct2, + * Enum: test$types.Enum, + * Enum2: test$types.Enum2, + * Enum3: test$types.Enum3, + * StructRenameAllUppercase: test$types.StructRenameAllUppercase, + * RenameSerdeSpecialChar: test$types.RenameSerdeSpecialChar, + * EnumRenameAllUppercase: test$types.EnumRenameAllUppercase, + * Recursive: test$types.Recursive, + * RecursiveMapValue: test$types.RecursiveMapValue, + * RecursiveTransparent: test$types.RecursiveTransparent, + * RecursiveInEnum: test$types.RecursiveInEnum, + * NonOptional: test$types.NonOptional, + * OptionalOnNamedField: test$types.OptionalOnNamedField, + * OptionalOnTransparentNamedField: test$types.OptionalOnTransparentNamedField, + * OptionalInEnum: test$types.OptionalInEnum, + * UntaggedVariants: test$types.UntaggedVariants, + * UntaggedVariantsWithoutValue: test$types.UntaggedVariantsWithoutValue, + * UntaggedVariantsWithDuplicateBranches: test$types.UntaggedVariantsWithDuplicateBranches, + * "HashMap": { [key in string]: null }, + * Regular: test$types.Regular, + * "HashMap": { [key in never]: null }, + * "HashMap": { [key in test$types.TransparentStruct]: null }, + * "HashMap": Partial<{ [key in test$types.UnitVariants]: null }>, + * "HashMap": Partial<{ [key in test$types.UntaggedVariantsKey]: null }>, + * ValidMaybeValidKey: test$types.ValidMaybeValidKey, + * ValidMaybeValidKeyNested: test$types.ValidMaybeValidKeyNested, + * MacroStruct: test$types.MacroStruct, + * MacroStruct2: test$types.MacroStruct2, + * MacroEnum: test$types.MacroEnum, + * DeprecatedType: test$types.DeprecatedType, + * DeprecatedTypeWithMsg: test$types.DeprecatedTypeWithMsg, + * DeprecatedTypeWithMsg2: test$types.DeprecatedTypeWithMsg2, + * DeprecatedFields: test$types.DeprecatedFields, + * DeprecatedTupleVariant: test$types.DeprecatedTupleVariant, + * DeprecatedEnumVariants: test$types.DeprecatedEnumVariants, + * CommentedStruct: test$types.CommentedStruct, + * CommentedEnum: test$types.CommentedEnum, + * SingleLineComment: test$types.SingleLineComment, + * NonGeneric: test$types.Demo, + * "HalfGenericA": test$types.Demo, + * "HalfGenericB": test$types.Demo, + * "FullGeneric": test$types.Demo, + * "Another": test$types.Demo, + * "MapA": { [key in string]: number }, + * "MapB": { [key in number]: string }, + * "MapC": { [key in string]: test$types.AGenericStruct }, + * "AGenericStruct": test$types.AGenericStruct, + * A: test$types.A, + * DoubleFlattened: test$types.DoubleFlattened, + * FlattenedInner: test$types.FlattenedInner, + * BoxFlattened: test$types.BoxFlattened, + * BoxInline: test$types.BoxInline, + * First: test$types.First, + * Second: test$types.Second, + * Third: test$types.Third, + * Fourth: test$types.Fourth, + * TagOnStructWithInline: test$types.TagOnStructWithInline, + * Sixth: test$types.Sixth, + * Seventh: test$types.Seventh, + * Eight: test$types.Eight, + * Ninth: test$types.Ninth, + * Tenth: test$types.Tenth, + * MyEnumTagged: test$types.MyEnumTagged, + * MyEnumExternal: test$types.MyEnumExternal, + * MyEnumAdjacent: test$types.MyEnumAdjacent, + * MyEnumUntagged: test$types.MyEnumUntagged, + * EmptyStruct: test$types.EmptyStruct, + * EmptyStructWithTag: test$types.EmptyStructWithTag, + * AdjacentlyTagged: test$types.AdjacentlyTagged, + * LoadProjectEvent: test$types.LoadProjectEvent, + * ExternallyTagged: test$types.ExternallyTagged, + * Issue221External: test$types.Issue221External, + * InternallyTaggedD: test$types.InternallyTaggedD, + * InternallyTaggedE: test$types.InternallyTaggedE, + * InternallyTaggedF: test$types.InternallyTaggedF, + * InternallyTaggedH: test$types.InternallyTaggedH, + * InternallyTaggedL: test$types.InternallyTaggedL, + * InternallyTaggedM: test$types.InternallyTaggedM, + * Issue221UntaggedSafe: test$types.Issue221UntaggedSafe, + * Issue221UntaggedMixed: test$types.Issue221UntaggedMixed, + * EmptyEnum: test$types.EmptyEnum, + * EmptyEnumTagged: test$types.EmptyEnumTagged, + * EmptyEnumTaggedWContent: test$types.EmptyEnumTaggedWContent, + * EmptyEnumUntagged: test$types.EmptyEnumUntagged, + * SkipOnlyField: test$types.SkipOnlyField, + * SkipField: test$types.SkipField, + * SkipVariant: test$types.SkipVariant, + * SkipUnnamedFieldInVariant: test$types.SkipUnnamedFieldInVariant, + * SkipNamedFieldInVariant: test$types.SkipNamedFieldInVariant, + * TransparentWithSkip: test$types.TransparentWithSkip, + * TransparentWithSkip2: test$types.TransparentWithSkip2, + * TransparentWithSkip3: test$types.TransparentWithSkip3, + * SkipVariant2: test$types.SkipVariant2, + * SkipVariant3: test$types.SkipVariant3, + * SkipStructFields: test$types.SkipStructFields, + * SpectaSkipNonTypeField: test$types.SpectaSkipNonTypeField, + * FlattenA: test$types.FlattenA, + * FlattenB: test$types.FlattenB, + * FlattenC: test$types.FlattenC, + * FlattenD: test$types.FlattenD, + * FlattenE: test$types.FlattenE, + * FlattenF: test$types.FlattenF, + * FlattenG: test$types.FlattenG, + * TupleNested: test$types.TupleNested, + * "Generic1<()>": test$types.Generic1, + * "GenericAutoBound<()>": test$types.GenericAutoBound, + * "GenericAutoBound2<()>": test$types.GenericAutoBound2, + * Container1: test$types.Container1, + * "Generic2<(), String, i32>": test$types.Generic2, + * "GenericNewType1<()>": test$types.GenericNewType1, + * "GenericTuple<()>": test$types.GenericTuple, + * "GenericStruct2<()>": test$types.GenericStruct2, + * "InlineGenericNewtype": string, + * "InlineGenericNested": [string, string[], [string, string], { [key in string]: string }, string | null, "Unit" | ({ Unnamed: string }) & { Named?: never } | ({ Named: { + * value: string, + * } }) & { Unnamed?: never }], + * "InlineFlattenGenericsG<()>": test$types.InlineFlattenGenericsG, + * InlineFlattenGenerics: test$types.InlineFlattenGenerics, + * GenericDefault: test$types.GenericDefault, + * ChainedGenericDefault: test$types.ChainedGenericDefault, + * "ChainedGenericDefault": test$types.ChainedGenericDefault, + * "ChainedGenericDefault": test$types.ChainedGenericDefault, + * "ChainedGenericDefault": test$types.ChainedGenericDefault, + * GenericDefaultSkipped: test$types.GenericDefaultSkipped, + * GenericDefaultSkippedNonType: test$types.GenericDefaultSkippedNonType, + * GenericParameterOrderPreserved: test$types.GenericParameterOrderPreserved, + * ConstGenericInNonConstContainer: test$types.ConstGenericInNonConstContainer, + * ConstGenericInConstContainer: test$types.ConstGenericInConstContainer, + * NamedConstGenericContainer: test$types.NamedConstGenericContainer, + * InlineConstGenericContainer: test$types.InlineConstGenericContainer, + * InlineRecursiveConstGenericContainer: test$types.InlineRecursiveConstGenericContainer, + * TestCollectionRegister: test$types.TestCollectionRegister, + * TestCollectionRegister: test$types.TestCollectionRegister, + * }} Primitives + * @property {number} i8 + * @property {number} i16 + * @property {number} i32 + * @property {number} u8 + * @property {number} u16 + * @property {number} u32 + * @property {number | null} f32 + * @property {number | null} f64 + * @property {boolean} bool + * @property {string} char + * @property {std$ops.Range} "Range" + * @property {std$ops.RangeInclusive} "RangeInclusive" + * @property {null} "()" + * @property {[string, number]} "(String, i32)" + * @property {[string, number, boolean]} "(String, i32, bool)" + * @property {[[string, number], [boolean, string, boolean], null]} "((String, i32), (bool, char, bool), ())" + * @property {[boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean]} "(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)" + * @property {[number[], boolean[]]} "(Vec, Vec)" + * @property {string} String + * @property {string} PathBuf + * @property {string} IpAddr + * @property {string} Ipv4Addr + * @property {string} Ipv6Addr + * @property {string} SocketAddr + * @property {string} SocketAddrV4 + * @property {string} SocketAddrV6 + * @property {string} "Cow<'static, str>" + * @property {number} "Cow<'static, i32>" + * @property {string} "&'static str" + * @property {boolean} "&'static bool" + * @property {number} "&'static i32" + * @property {number[]} "Vec" + * @property {number[]} "&'static [i32]" + * @property {[number, number, number]} "&'static [i32; 3]" + * @property {[number, number, number]} "[i32; 3]" + * @property {test$types.MyEnum[]} "Vec" + * @property {test$types.MyEnum[]} "&'static [MyEnum]" + * @property {[test$types.MyEnum, test$types.MyEnum, test$types.MyEnum, test$types.MyEnum, test$types.MyEnum, test$types.MyEnum]} "&'static [MyEnum; 6]" + * @property {[test$types.MyEnum, test$types.MyEnum]} "[MyEnum; 2]" + * @property {[number]} "&'static [i32; 1]" + * @property {[]} "&'static [i32; 0]" + * @property {number | null} "Option" + * @property {null} "Option<()>" + * @property {number[] | null} "Option>" + * @property {std$result.Result} "Result" + * @property {(number | null)[]} "Vec>>" + * @property {number[] | null} "Option>>" + * @property {[string[], string[], string[]]} "[Vec; 3]" + * @property {string | null} "Option>" + * @property {string | null} "Option>>" + * @property {null} "PhantomData<()>" + * @property {null} "PhantomData" + * @property {never} Infallible + * @property {test$types.Unit1} Unit1 + * @property {test$types.Unit2} Unit2 + * @property {test$types.Unit3} Unit3 + * @property {test$types.Unit4} Unit4 + * @property {test$types.Unit5} Unit5 + * @property {test$types.Unit6} Unit6 + * @property {test$types.Unit7} Unit7 + * @property {test$types.SimpleStruct} SimpleStruct + * @property {test$types.TupleStruct1} TupleStruct1 + * @property {test$types.TupleStruct3} TupleStruct3 + * @property {test$types.TestEnum} TestEnum + * @property {test$types.RefStruct} RefStruct + * @property {test$types.InlinerStruct} InlinerStruct + * @property {test$types.GenericStruct} "GenericStruct" + * @property {test$types.GenericStruct} "GenericStruct" + * @property {test$types.FlattenEnumStruct} FlattenEnumStruct + * @property {test$types.OverridenStruct} OverridenStruct + * @property {test$types.HasGenericAlias} HasGenericAlias + * @property {test$types.EnumMacroAttributes} EnumMacroAttributes + * @property {test$types.InlineEnumField} InlineEnumField + * @property {test$types.InlineOptionalType} InlineOptionalType + * @property {test$types.Rename} Rename + * @property {test$types.TransparentType} TransparentType + * @property {test$types.TransparentType2} TransparentType2 + * @property {test$types.TransparentTypeWithOverride} TransparentTypeWithOverride + * @property {[(number | null), (number | null), (number | null)]} "[Option; 3]" + * @property {Partial<{ [key in test$types.BasicEnum]: null }>} "HashMap" + * @property {Partial<{ [key in test$types.BasicEnum]: number }>} "HashMap" + * @property {number | null} "Option>>>" + * @property {test$types.PlaceholderInnerField[]} "Vec" + * @property {test$types.EnumReferenceRecordKey} EnumReferenceRecordKey + * @property {test$types.FlattenOnNestedEnum} FlattenOnNestedEnum + * @property {test$types.MyEmptyInput} MyEmptyInput + * @property {string} "(String)" + * @property {[string]} "(String,)" + * @property {test$types.ExtraBracketsInTupleVariant} ExtraBracketsInTupleVariant + * @property {test$types.ExtraBracketsInUnnamedStruct} ExtraBracketsInUnnamedStruct + * @property {test$types.MyEnum[]} "Vec" + * @property {test$types.InlineTuple} InlineTuple + * @property {test$types.InlineTuple2} InlineTuple2 + * @property {string} "Box" + * @property {string} "Box" + * @property {test$types.SkippedFieldWithinVariant} SkippedFieldWithinVariant + * @property {test$types.KebabCase} KebabCase + * @property {string[]} "&[&str]" + * @property {test$types.Issue281} "Issue281<'_>" + * @property {test$types.LifetimeGenericStruct} "LifetimeGenericStruct<'_, i32>" + * @property {test$types.LifetimeGenericEnum} "LifetimeGenericEnum<'_, i32>" + * @property {test$types.RenameWithWeirdCharsField} RenameWithWeirdCharsField + * @property {test$types.RenameWithWeirdCharsVariant} RenameWithWeirdCharsVariant + * @property {test$types.RenamedFieldKeys} RenamedFieldKeys + * @property {test$types.RenamedVariantWithSkippedPayload} RenamedVariantWithSkippedPayload + * @property {test$types$type_type.Type} "type_type::Type" + * @property {test$types.ActualType} ActualType + * @property {test$types.SpectaTypeOverride} SpectaTypeOverride + * @property {test$types.ContainerTypeOverrideStruct} ContainerTypeOverrideStruct + * @property {test$types.ContainerTypeOverrideEnum} ContainerTypeOverrideEnum + * @property {test$types.ContainerTypeOverrideGeneric} "ContainerTypeOverrideGeneric>" + * @property {test$types.ContainerTypeOverrideToGeneric} "ContainerTypeOverrideToGeneric" + * @property {test$types.ContainerTypeOverrideTuple} ContainerTypeOverrideTuple + * @property {test$types.ContainerTypeOverrideTupleGeneric} "ContainerTypeOverrideTupleGeneric" + * @property {test$types.InvalidToValidType} InvalidToValidType + * @property {test$types.TupleStruct} TupleStruct + * @property {test$types.TupleStructWithRep} TupleStructWithRep + * @property {test$types.GenericTupleStruct} "GenericTupleStruct" + * @property {test$types.BracedStruct} BracedStruct + * @property {test$types.StructNew} Struct + * @property {test$types.Struct2} Struct2 + * @property {test$types.Enum} Enum + * @property {test$types.Enum2} Enum2 + * @property {test$types.Enum3} Enum3 + * @property {test$types.StructRenameAllUppercase} StructRenameAllUppercase + * @property {test$types.RenameSerdeSpecialChar} RenameSerdeSpecialChar + * @property {test$types.EnumRenameAllUppercase} EnumRenameAllUppercase + * @property {test$types.Recursive} Recursive + * @property {test$types.RecursiveMapValue} RecursiveMapValue + * @property {test$types.RecursiveTransparent} RecursiveTransparent + * @property {test$types.RecursiveInEnum} RecursiveInEnum + * @property {test$types.NonOptional} NonOptional + * @property {test$types.OptionalOnNamedField} OptionalOnNamedField + * @property {test$types.OptionalOnTransparentNamedField} OptionalOnTransparentNamedField + * @property {test$types.OptionalInEnum} OptionalInEnum + * @property {test$types.UntaggedVariants} UntaggedVariants + * @property {test$types.UntaggedVariantsWithoutValue} UntaggedVariantsWithoutValue + * @property {test$types.UntaggedVariantsWithDuplicateBranches} UntaggedVariantsWithDuplicateBranches + * @property {{ [key in string]: null }} "HashMap" + * @property {test$types.Regular} Regular + * @property {{ [key in never]: null }} "HashMap" + * @property {{ [key in test$types.TransparentStruct]: null }} "HashMap" + * @property {Partial<{ [key in test$types.UnitVariants]: null }>} "HashMap" + * @property {Partial<{ [key in test$types.UntaggedVariantsKey]: null }>} "HashMap" + * @property {test$types.ValidMaybeValidKey} ValidMaybeValidKey + * @property {test$types.ValidMaybeValidKeyNested} ValidMaybeValidKeyNested + * @property {test$types.MacroStruct} MacroStruct + * @property {test$types.MacroStruct2} MacroStruct2 + * @property {test$types.MacroEnum} MacroEnum + * @property {test$types.DeprecatedType} DeprecatedType + * @property {test$types.DeprecatedTypeWithMsg} DeprecatedTypeWithMsg + * @property {test$types.DeprecatedTypeWithMsg2} DeprecatedTypeWithMsg2 + * @property {test$types.DeprecatedFields} DeprecatedFields + * @property {test$types.DeprecatedTupleVariant} DeprecatedTupleVariant + * @property {test$types.DeprecatedEnumVariants} DeprecatedEnumVariants + * @property {test$types.CommentedStruct} CommentedStruct + * @property {test$types.CommentedEnum} CommentedEnum + * @property {test$types.SingleLineComment} SingleLineComment + * @property {test$types.Demo} NonGeneric + * @property {test$types.Demo} "HalfGenericA" + * @property {test$types.Demo} "HalfGenericB" + * @property {test$types.Demo} "FullGeneric" + * @property {test$types.Demo} "Another" + * @property {{ [key in string]: number }} "MapA" + * @property {{ [key in number]: string }} "MapB" + * @property {{ [key in string]: test$types.AGenericStruct }} "MapC" + * @property {test$types.AGenericStruct} "AGenericStruct" + * @property {test$types.A} A + * @property {test$types.DoubleFlattened} DoubleFlattened + * @property {test$types.FlattenedInner} FlattenedInner + * @property {test$types.BoxFlattened} BoxFlattened + * @property {test$types.BoxInline} BoxInline + * @property {test$types.First} First + * @property {test$types.Second} Second + * @property {test$types.Third} Third + * @property {test$types.Fourth} Fourth + * @property {test$types.TagOnStructWithInline} TagOnStructWithInline + * @property {test$types.Sixth} Sixth + * @property {test$types.Seventh} Seventh + * @property {test$types.Eight} Eight + * @property {test$types.Ninth} Ninth + * @property {test$types.Tenth} Tenth + * @property {test$types.MyEnumTagged} MyEnumTagged + * @property {test$types.MyEnumExternal} MyEnumExternal + * @property {test$types.MyEnumAdjacent} MyEnumAdjacent + * @property {test$types.MyEnumUntagged} MyEnumUntagged + * @property {test$types.EmptyStruct} EmptyStruct + * @property {test$types.EmptyStructWithTag} EmptyStructWithTag + * @property {test$types.AdjacentlyTagged} AdjacentlyTagged + * @property {test$types.LoadProjectEvent} LoadProjectEvent + * @property {test$types.ExternallyTagged} ExternallyTagged + * @property {test$types.Issue221External} Issue221External + * @property {test$types.InternallyTaggedD} InternallyTaggedD + * @property {test$types.InternallyTaggedE} InternallyTaggedE + * @property {test$types.InternallyTaggedF} InternallyTaggedF + * @property {test$types.InternallyTaggedH} InternallyTaggedH + * @property {test$types.InternallyTaggedL} InternallyTaggedL + * @property {test$types.InternallyTaggedM} InternallyTaggedM + * @property {test$types.Issue221UntaggedSafe} Issue221UntaggedSafe + * @property {test$types.Issue221UntaggedMixed} Issue221UntaggedMixed + * @property {test$types.EmptyEnum} EmptyEnum + * @property {test$types.EmptyEnumTagged} EmptyEnumTagged + * @property {test$types.EmptyEnumTaggedWContent} EmptyEnumTaggedWContent + * @property {test$types.EmptyEnumUntagged} EmptyEnumUntagged + * @property {test$types.SkipOnlyField} SkipOnlyField + * @property {test$types.SkipField} SkipField + * @property {test$types.SkipVariant} SkipVariant + * @property {test$types.SkipUnnamedFieldInVariant} SkipUnnamedFieldInVariant + * @property {test$types.SkipNamedFieldInVariant} SkipNamedFieldInVariant + * @property {test$types.TransparentWithSkip} TransparentWithSkip + * @property {test$types.TransparentWithSkip2} TransparentWithSkip2 + * @property {test$types.TransparentWithSkip3} TransparentWithSkip3 + * @property {test$types.SkipVariant2} SkipVariant2 + * @property {test$types.SkipVariant3} SkipVariant3 + * @property {test$types.SkipStructFields} SkipStructFields + * @property {test$types.SpectaSkipNonTypeField} SpectaSkipNonTypeField + * @property {test$types.FlattenA} FlattenA + * @property {test$types.FlattenB} FlattenB + * @property {test$types.FlattenC} FlattenC + * @property {test$types.FlattenD} FlattenD + * @property {test$types.FlattenE} FlattenE + * @property {test$types.FlattenF} FlattenF + * @property {test$types.FlattenG} FlattenG + * @property {test$types.TupleNested} TupleNested + * @property {test$types.Generic1} "Generic1<()>" + * @property {test$types.GenericAutoBound} "GenericAutoBound<()>" + * @property {test$types.GenericAutoBound2} "GenericAutoBound2<()>" + * @property {test$types.Container1} Container1 + * @property {test$types.Generic2} "Generic2<(), String, i32>" + * @property {test$types.GenericNewType1} "GenericNewType1<()>" + * @property {test$types.GenericTuple} "GenericTuple<()>" + * @property {test$types.GenericStruct2} "GenericStruct2<()>" + * @property {string} "InlineGenericNewtype" + * @property {[string, string[], [string, string], { [key in string]: string }, string | null, "Unit" | ({ Unnamed: string }) & { Named?: never } | ({ Named: { + * value: string, + * } }) & { Unnamed?: never }]} "InlineGenericNested" + * @property {test$types.InlineFlattenGenericsG} "InlineFlattenGenericsG<()>" + * @property {test$types.InlineFlattenGenerics} InlineFlattenGenerics + * @property {test$types.GenericDefault} GenericDefault + * @property {test$types.ChainedGenericDefault} ChainedGenericDefault + * @property {test$types.ChainedGenericDefault} "ChainedGenericDefault" + * @property {test$types.ChainedGenericDefault} "ChainedGenericDefault" + * @property {test$types.ChainedGenericDefault} "ChainedGenericDefault" + * @property {test$types.GenericDefaultSkipped} GenericDefaultSkipped + * @property {test$types.GenericDefaultSkippedNonType} GenericDefaultSkippedNonType + * @property {test$types.GenericParameterOrderPreserved} GenericParameterOrderPreserved + * @property {test$types.ConstGenericInNonConstContainer} ConstGenericInNonConstContainer + * @property {test$types.ConstGenericInConstContainer} ConstGenericInConstContainer + * @property {test$types.NamedConstGenericContainer} NamedConstGenericContainer + * @property {test$types.InlineConstGenericContainer} InlineConstGenericContainer + * @property {test$types.InlineRecursiveConstGenericContainer} InlineRecursiveConstGenericContainer + * @property {test$types.TestCollectionRegister} TestCollectionRegister + * @property {test$types.TestCollectionRegister} TestCollectionRegister + */ + ════════════════════════════════════════ diff --git a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-flatfile-serde.snap b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-flatfile-serde.snap index 40d94aea..cdbbf839 100644 --- a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-flatfile-serde.snap +++ b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-flatfile-serde.snap @@ -1,8 +1,9 @@ --- source: tests/tests/jsdoc.rs +assertion_line: 78 expression: output --- -jsdoc-export-to-flatfile-serde (52813 bytes) +jsdoc-export-to-flatfile-serde (52817 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. /** @@ -825,8 +826,12 @@ jsdoc-export-to-flatfile-serde (52813 bytes) * inner: First, * } }} Variant * - * @typedef {{ type: "Variant"; inner: First }} MyEnumTagged - * @property {{ type: "Variant"; inner: First }} Variant + * @typedef {{ + * type: "Variant", + * } & First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & First} Variant * * @typedef {{ inner: First }} MyEnumUntagged * @property {{ inner: First }} Variant diff --git a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-flatfile-serde_phases.snap b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-flatfile-serde_phases.snap index 14f7ab39..9cdf5719 100644 --- a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-flatfile-serde_phases.snap +++ b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-flatfile-serde_phases.snap @@ -2,7 +2,7 @@ source: tests/tests/jsdoc.rs expression: output --- -jsdoc-export-to-flatfile-serde_phases (61045 bytes) +jsdoc-export-to-flatfile-serde_phases (60947 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. /** @@ -794,27 +794,21 @@ jsdoc-export-to-flatfile-serde_phases (61045 bytes) * @property {InternallyTaggedWithAlias_Serialize} Serialize * @property {InternallyTaggedWithAlias_Deserialize} Deserialize * - * @typedef {({ A: { + * @typedef {{ * type: "A", * } & { * field: string, * } | { * bruh: string, - * } }) & { B?: never } | ({ B: { - * type: "B", - * other: number, - * } }) & { A?: never }} InternallyTaggedWithAlias_Deserialize - * @property {{ A: { + * } | { type: "B"; other: number }} InternallyTaggedWithAlias_Deserialize + * @property {{ * type: "A", * } & { * field: string, * } | { * bruh: string, - * } }} A - * @property {{ B: { - * type: "B", - * other: number, - * } }} B + * }} A + * @property {{ type: "B"; other: number }} B * * @typedef {({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }} InternallyTaggedWithAlias_Serialize * @property {{ type: "A"; field: string }} A @@ -951,8 +945,12 @@ jsdoc-export-to-flatfile-serde_phases (61045 bytes) * inner: First, * } }} Variant * - * @typedef {{ type: "Variant"; inner: First }} MyEnumTagged - * @property {{ type: "Variant"; inner: First }} Variant + * @typedef {{ + * type: "Variant", + * } & First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & First} Variant * * @typedef {{ inner: First }} MyEnumUntagged * @property {{ inner: First }} Variant @@ -1031,12 +1029,12 @@ jsdoc-export-to-flatfile-serde_phases (61045 bytes) * @typedef {{ * a: number | null, * b?: number | null, - * c?: string | null, + * c?: string, * d: boolean, * }} Optional_Serialize * @property {number | null} a * @property {number | null} [b] - * @property {string | null} [c] + * @property {string} [c] * @property {boolean} d * * @typedef {{ diff --git a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-moduleprefixedname-serde.snap b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-moduleprefixedname-serde.snap index c3ad97cb..5535ff3a 100644 --- a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-moduleprefixedname-serde.snap +++ b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-moduleprefixedname-serde.snap @@ -1,8 +1,9 @@ --- source: tests/tests/jsdoc.rs +assertion_line: 78 expression: output --- -jsdoc-export-to-moduleprefixedname-serde (58299 bytes) +jsdoc-export-to-moduleprefixedname-serde (58303 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. /** @@ -825,8 +826,12 @@ jsdoc-export-to-moduleprefixedname-serde (58299 bytes) * inner: test_types_First, * } }} Variant * - * @typedef {{ type: "Variant"; inner: test_types_First }} MyEnumTagged - * @property {{ type: "Variant"; inner: test_types_First }} Variant + * @typedef {{ + * type: "Variant", + * } & test_types_First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & test_types_First} Variant * * @typedef {{ inner: test_types_First }} MyEnumUntagged * @property {{ inner: test_types_First }} Variant diff --git a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-moduleprefixedname-serde_phases.snap b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-moduleprefixedname-serde_phases.snap index 46baedca..d6683a18 100644 --- a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-moduleprefixedname-serde_phases.snap +++ b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-moduleprefixedname-serde_phases.snap @@ -2,7 +2,7 @@ source: tests/tests/jsdoc.rs expression: output --- -jsdoc-export-to-moduleprefixedname-serde_phases (67059 bytes) +jsdoc-export-to-moduleprefixedname-serde_phases (66961 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. /** @@ -794,27 +794,21 @@ jsdoc-export-to-moduleprefixedname-serde_phases (67059 bytes) * @property {test_types_InternallyTaggedWithAlias_Serialize} Serialize * @property {test_types_InternallyTaggedWithAlias_Deserialize} Deserialize * - * @typedef {({ A: { + * @typedef {{ * type: "A", * } & { * field: string, * } | { * bruh: string, - * } }) & { B?: never } | ({ B: { - * type: "B", - * other: number, - * } }) & { A?: never }} InternallyTaggedWithAlias_Deserialize - * @property {{ A: { + * } | { type: "B"; other: number }} InternallyTaggedWithAlias_Deserialize + * @property {{ * type: "A", * } & { * field: string, * } | { * bruh: string, - * } }} A - * @property {{ B: { - * type: "B", - * other: number, - * } }} B + * }} A + * @property {{ type: "B"; other: number }} B * * @typedef {({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }} InternallyTaggedWithAlias_Serialize * @property {{ type: "A"; field: string }} A @@ -951,8 +945,12 @@ jsdoc-export-to-moduleprefixedname-serde_phases (67059 bytes) * inner: test_types_First, * } }} Variant * - * @typedef {{ type: "Variant"; inner: test_types_First }} MyEnumTagged - * @property {{ type: "Variant"; inner: test_types_First }} Variant + * @typedef {{ + * type: "Variant", + * } & test_types_First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & test_types_First} Variant * * @typedef {{ inner: test_types_First }} MyEnumUntagged * @property {{ inner: test_types_First }} Variant @@ -1031,12 +1029,12 @@ jsdoc-export-to-moduleprefixedname-serde_phases (67059 bytes) * @typedef {{ * a: number | null, * b?: number | null, - * c?: string | null, + * c?: string, * d: boolean, * }} Optional_Serialize * @property {number | null} a * @property {number | null} [b] - * @property {string | null} [c] + * @property {string} [c] * @property {boolean} d * * @typedef {{ diff --git a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-namespaces-serde.snap b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-namespaces-serde.snap index 816f455e..21cc33c1 100644 --- a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-namespaces-serde.snap +++ b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-namespaces-serde.snap @@ -1,8 +1,9 @@ --- source: tests/tests/jsdoc.rs +assertion_line: 78 expression: output --- -jsdoc-export-to-namespaces-serde (66529 bytes) +jsdoc-export-to-namespaces-serde (66545 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. @@ -863,8 +864,12 @@ namespace $s$ { * inner: $s$.test.types.First, * } }} Variant * - * @typedef {{ type: "Variant"; inner: $s$.test.types.First }} MyEnumTagged - * @property {{ type: "Variant"; inner: $s$.test.types.First }} Variant + * @typedef {{ + * type: "Variant", + * } & $s$.test.types.First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & $s$.test.types.First} Variant * * @typedef {{ inner: $s$.test.types.First }} MyEnumUntagged * @property {{ inner: $s$.test.types.First }} Variant diff --git a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-namespaces-serde_phases.snap b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-namespaces-serde_phases.snap index f33b7fbc..20d1982a 100644 --- a/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-namespaces-serde_phases.snap +++ b/tests/tests/snapshots/test__jsdoc__jsdoc-export-to-namespaces-serde_phases.snap @@ -2,7 +2,7 @@ source: tests/tests/jsdoc.rs expression: output --- -jsdoc-export-to-namespaces-serde_phases (76348 bytes) +jsdoc-export-to-namespaces-serde_phases (76244 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. @@ -832,27 +832,21 @@ namespace $s$ { * @property {$s$.test.types.InternallyTaggedWithAlias_Serialize} Serialize * @property {$s$.test.types.InternallyTaggedWithAlias_Deserialize} Deserialize * - * @typedef {({ A: { + * @typedef {{ * type: "A", * } & { * field: string, * } | { * bruh: string, - * } }) & { B?: never } | ({ B: { - * type: "B", - * other: number, - * } }) & { A?: never }} InternallyTaggedWithAlias_Deserialize - * @property {{ A: { + * } | { type: "B"; other: number }} InternallyTaggedWithAlias_Deserialize + * @property {{ * type: "A", * } & { * field: string, * } | { * bruh: string, - * } }} A - * @property {{ B: { - * type: "B", - * other: number, - * } }} B + * }} A + * @property {{ type: "B"; other: number }} B * * @typedef {({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }} InternallyTaggedWithAlias_Serialize * @property {{ type: "A"; field: string }} A @@ -989,8 +983,12 @@ namespace $s$ { * inner: $s$.test.types.First, * } }} Variant * - * @typedef {{ type: "Variant"; inner: $s$.test.types.First }} MyEnumTagged - * @property {{ type: "Variant"; inner: $s$.test.types.First }} Variant + * @typedef {{ + * type: "Variant", + * } & $s$.test.types.First} MyEnumTagged + * @property {{ + * type: "Variant", + * } & $s$.test.types.First} Variant * * @typedef {{ inner: $s$.test.types.First }} MyEnumUntagged * @property {{ inner: $s$.test.types.First }} Variant @@ -1069,12 +1067,12 @@ namespace $s$ { * @typedef {{ * a: number | null, * b?: number | null, - * c?: string | null, + * c?: string, * d: boolean, * }} Optional_Serialize * @property {number | null} a * @property {number | null} [b] - * @property {string | null} [c] + * @property {string} [c] * @property {boolean} d * * @typedef {{ diff --git a/tests/tests/snapshots/test__serde_conversions__serde-conversions-format-phases-option-is-none-omits-null.snap b/tests/tests/snapshots/test__serde_conversions__serde-conversions-format-phases-option-is-none-omits-null.snap new file mode 100644 index 00000000..76af30b8 --- /dev/null +++ b/tests/tests/snapshots/test__serde_conversions__serde-conversions-format-phases-option-is-none-omits-null.snap @@ -0,0 +1,25 @@ +--- +source: tests/tests/serde_conversions.rs +assertion_line: 433 +expression: rendered +--- +// This file has been generated by Specta. Do not edit this file manually. +export type DefaultedSkipSerializingIfOnly = DefaultedSkipSerializingIfOnly_Serialize | DefaultedSkipSerializingIfOnly_Deserialize; + +export type DefaultedSkipSerializingIfOnly_Deserialize = { + value?: string | null, +}; + +export type DefaultedSkipSerializingIfOnly_Serialize = { + value?: string, +}; + +export type SkipSerializingIfOnly = SkipSerializingIfOnly_Serialize | SkipSerializingIfOnly_Deserialize; + +export type SkipSerializingIfOnly_Deserialize = { + value: string | null, +}; + +export type SkipSerializingIfOnly_Serialize = { + value?: string, +}; diff --git a/tests/tests/snapshots/test__serde_other__serde-other-adjacent-tag-typescript.snap b/tests/tests/snapshots/test__serde_other__serde-other-adjacent-tag-typescript.snap index 0dce90fc..0a091ac6 100644 --- a/tests/tests/snapshots/test__serde_other__serde-other-adjacent-tag-typescript.snap +++ b/tests/tests/snapshots/test__serde_other__serde-other-adjacent-tag-typescript.snap @@ -1,15 +1,11 @@ --- source: tests/tests/serde_other.rs +assertion_line: 63 expression: ts --- // This file has been generated by Specta. Do not edit this file manually. export type AdjacentOther = AdjacentOther_Serialize | AdjacentOther_Deserialize; -export type AdjacentOther_Deserialize = ({ known: { - kind: "known", - data: string, -} }) & { Other?: never } | ({ Other: { - kind: string, -} }) & { known?: never }; +export type AdjacentOther_Deserialize = { kind: "known"; data: string } | ({ kind: string }) & { data?: never }; export type AdjacentOther_Serialize = { kind: "known"; data: string } | ({ kind: "Other" }) & { data?: never }; diff --git a/tests/tests/snapshots/test__serde_other__serde-other-internal-tag-typescript.snap b/tests/tests/snapshots/test__serde_other__serde-other-internal-tag-typescript.snap index ad1f0e30..e4b3e0a8 100644 --- a/tests/tests/snapshots/test__serde_other__serde-other-internal-tag-typescript.snap +++ b/tests/tests/snapshots/test__serde_other__serde-other-internal-tag-typescript.snap @@ -1,14 +1,11 @@ --- source: tests/tests/serde_other.rs +assertion_line: 51 expression: ts --- // This file has been generated by Specta. Do not edit this file manually. export type InternalOther = InternalOther_Serialize | InternalOther_Deserialize; -export type InternalOther_Deserialize = ({ known: { - kind: "known", -} }) & { Other?: never } | ({ Other: { - kind: string, -} }) & { known?: never }; +export type InternalOther_Deserialize = { kind: "known" } | { kind: string }; export type InternalOther_Serialize = { kind: "known" } | { kind: "Other" }; diff --git a/tests/tests/snapshots/test__typescript__export-many-serde.snap b/tests/tests/snapshots/test__typescript__export-many-serde.snap index ac0ee723..f41fedd8 100644 --- a/tests/tests/snapshots/test__typescript__export-many-serde.snap +++ b/tests/tests/snapshots/test__typescript__export-many-serde.snap @@ -1,5 +1,6 @@ --- source: tests/tests/typescript.rs +assertion_line: 1011 expression: output --- export type Range = { @@ -484,7 +485,9 @@ export type Tenth = string | "B" | { a: string, } | First; -export type MyEnumTagged = { type: "Variant"; inner: First }; +export type MyEnumTagged = { + type: "Variant", +} & First; export type MyEnumExternal = { Variant: { inner: First, diff --git a/tests/tests/snapshots/test__typescript__export-many-serde_phases.snap b/tests/tests/snapshots/test__typescript__export-many-serde_phases.snap index ab9de9a4..4be63b09 100644 --- a/tests/tests/snapshots/test__typescript__export-many-serde_phases.snap +++ b/tests/tests/snapshots/test__typescript__export-many-serde_phases.snap @@ -1,5 +1,6 @@ --- source: tests/tests/typescript.rs +assertion_line: 1011 expression: output --- /** https://github.com/specta-rs/specta/issues/374 */ @@ -509,7 +510,9 @@ export type Tenth = string | "B" | { a: string, } | First; -export type MyEnumTagged = { type: "Variant"; inner: First }; +export type MyEnumTagged = { + type: "Variant", +} & First; export type MyEnumExternal = { Variant: { inner: First, diff --git a/tests/tests/snapshots/test__typescript__export-serde.snap b/tests/tests/snapshots/test__typescript__export-serde.snap index 39af4e85..4edeea89 100644 --- a/tests/tests/snapshots/test__typescript__export-serde.snap +++ b/tests/tests/snapshots/test__typescript__export-serde.snap @@ -1,5 +1,6 @@ --- source: tests/tests/typescript.rs +assertion_line: 982 expression: output --- Range: export type Range = { @@ -515,7 +516,9 @@ Tenth: export type Tenth = string | "B" | { a: string, } | First; -MyEnumTagged: export type MyEnumTagged = { type: "Variant"; inner: First }; +MyEnumTagged: export type MyEnumTagged = { + type: "Variant", +} & First; MyEnumExternal: export type MyEnumExternal = { Variant: { inner: First, diff --git a/tests/tests/snapshots/test__typescript__export-serde_phases.snap b/tests/tests/snapshots/test__typescript__export-serde_phases.snap index 67fe4145..1c30b5a0 100644 --- a/tests/tests/snapshots/test__typescript__export-serde_phases.snap +++ b/tests/tests/snapshots/test__typescript__export-serde_phases.snap @@ -1,5 +1,6 @@ --- source: tests/tests/typescript.rs +assertion_line: 982 expression: output --- Issue374: /** https://github.com/specta-rs/specta/issues/374 */ @@ -540,7 +541,9 @@ Tenth: export type Tenth = string | "B" | { a: string, } | First; -MyEnumTagged: export type MyEnumTagged = { type: "Variant"; inner: First }; +MyEnumTagged: export type MyEnumTagged = { + type: "Variant", +} & First; MyEnumExternal: export type MyEnumExternal = { Variant: { inner: First, diff --git a/tests/tests/snapshots/test__typescript__inline-serde.snap b/tests/tests/snapshots/test__typescript__inline-serde.snap index cce3bb32..d30daea0 100644 --- a/tests/tests/snapshots/test__typescript__inline-serde.snap +++ b/tests/tests/snapshots/test__typescript__inline-serde.snap @@ -1,5 +1,6 @@ --- source: tests/tests/typescript.rs +assertion_line: 1060 expression: output --- i8: number @@ -425,7 +426,9 @@ Ninth: { t: "A"; c: string } | { t: "B" } | { t: "C"; c: { Tenth: string | "B" | { a: string, } | First -MyEnumTagged: { type: "Variant"; inner: First } +MyEnumTagged: { + type: "Variant", +} & First MyEnumExternal: { Variant: { inner: First, } } diff --git a/tests/tests/snapshots/test__typescript__inline-serde_phases.snap b/tests/tests/snapshots/test__typescript__inline-serde_phases.snap index 0e0c99d7..8539acbc 100644 --- a/tests/tests/snapshots/test__typescript__inline-serde_phases.snap +++ b/tests/tests/snapshots/test__typescript__inline-serde_phases.snap @@ -9,7 +9,7 @@ Issue374: { Optional: { a: number | null, b?: number | null, - c?: string | null, + c?: string, d: boolean, } StructPhaseSpecificRename: { @@ -458,7 +458,9 @@ Ninth: { t: "A"; c: string } | { t: "B" } | { t: "C"; c: { Tenth: string | "B" | { a: string, } | First -MyEnumTagged: { type: "Variant"; inner: First } +MyEnumTagged: { + type: "Variant", +} & First MyEnumExternal: { Variant: { inner: First, } } diff --git a/tests/tests/snapshots/test__typescript__inline-serde_phases.snap.new b/tests/tests/snapshots/test__typescript__inline-serde_phases.snap.new new file mode 100644 index 00000000..b39c1292 --- /dev/null +++ b/tests/tests/snapshots/test__typescript__inline-serde_phases.snap.new @@ -0,0 +1,696 @@ +--- +source: tests/tests/typescript.rs +assertion_line: 1060 +expression: output +--- +Issue374: { + foo?: boolean, + bar?: boolean, +} +Optional: { + a: number | null, + b?: number | null, + c?: string, + d: boolean, +} +StructPhaseSpecificRename: { + kind: "StructPhaseSpecificRenameSerialize", + ser: string, +} +StructWithAlias: { + field: string, +} +StructWithMultipleAliases: { + field: string, +} +StructWithAliasAndRename: { + renamed_field: string, +} +EnumWithVariantAlias: "Variant" | "Other" +EnumWithMultipleVariantAliases: "Variant" | "Other" +EnumWithVariantAliasAndRename: "renamed_variant" | "Other" +InternallyTaggedWithAlias: ({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never } +AdjacentlyTaggedWithAlias: { type: "A"; data: { + field: string, +} } | { type: "B"; data: { + other: number, +} } +UntaggedWithAlias: ({ field: string }) & { other?: never } | ({ other: number }) & { field?: never } +i8: number +i16: number +i32: number +u8: number +u16: number +u32: number +f32: number | null +f64: number | null +bool: boolean +char: string +Range: { + start: T, + end: T, +} +RangeInclusive: { + start: T, + end: T, +} +(): null +(String, i32): [string, number] +(String, i32, bool): [string, number, boolean] +((String, i32), (bool, char, bool), ()): [[string, number], [boolean, string, boolean], null] +(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool): [boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean] +(Vec, Vec): [number[], boolean[]] +String: string +PathBuf: string +IpAddr: string +Ipv4Addr: string +Ipv6Addr: string +SocketAddr: string +SocketAddrV4: string +SocketAddrV6: string +Cow<'static, str>: string +Cow<'static, i32>: number +&'static str: string +&'static bool: boolean +&'static i32: number +Vec: number[] +&'static [i32]: number[] +&'static [i32; 3]: [number, number, number] +[i32; 3]: [number, number, number] +Vec: MyEnum[] +&'static [MyEnum]: MyEnum[] +&'static [MyEnum; 6]: [MyEnum, MyEnum, MyEnum, MyEnum, MyEnum, MyEnum] +[MyEnum; 2]: [MyEnum, MyEnum] +&'static [i32; 1]: [number] +&'static [i32; 0]: [] +Option: number | null +Option<()>: null +Option>: number[] | null +Result: { + ok: T, + err: E, +} +Vec>>: (number | null)[] +Option>>: number[] | null +[Vec; 3]: [string[], string[], string[]] +Option>: string | null +Option>>: string | null +PhantomData<()>: null +PhantomData: null +Infallible: never +Unit1: null +Unit2: Record +Unit3: [] +Unit4: null +Unit5: "A" +Unit6: { A: null } +Unit7: { A: Record } +SimpleStruct: { + a: number, + b: string, + c: [number, string, number], + d: string[], + e: string | null, +} +TupleStruct1: number +TupleStruct3: [number, boolean, string] +TestEnum: "Unit" | ({ Single: number }) & { Multiple?: never; Struct?: never } | ({ Multiple: [number, number] }) & { Single?: never; Struct?: never } | ({ Struct: { + a: number, +} }) & { Multiple?: never; Single?: never } +RefStruct: TestEnum +InlinerStruct: { + inline_this: { + ref_struct: SimpleStruct, + val: number, + }, + dont_inline_this: RefStruct, +} +GenericStruct: { + arg: T, +} +GenericStruct: { + arg: T, +} +FlattenEnumStruct: ({ + outer: string, +}) & (FlattenEnum) +OverridenStruct: { + overriden_field: string, +} +HasGenericAlias: { [key in number]: string } +EnumMacroAttributes: ({ A: string }) & { D?: never; bbb?: never; cccc?: never } | ({ bbb: number }) & { A?: never; D?: never; cccc?: never } | ({ cccc: number }) & { A?: never; D?: never; bbb?: never } | ({ D: { + a: string, + bbbbbb: number, +} }) & { A?: never; bbb?: never; cccc?: never } +InlineEnumField: { A: { + a: string, +} } +InlineOptionalType: { + optional_field: { + a: string, +} | null, +} +Rename: "OneWord" | "Two words" +TransparentType: TransparentTypeInner +TransparentType2: null +TransparentTypeWithOverride: string +[Option; 3]: [(number | null), (number | null), (number | null)] +HashMap: Partial<{ [key in BasicEnum]: null }> +HashMap: Partial<{ [key in BasicEnum]: number }> +Option>>>: number | null +Vec: PlaceholderInnerField[] +EnumReferenceRecordKey: { + a: Partial<{ [key in BasicEnum]: number }>, +} +FlattenOnNestedEnum: ({ + id: string, +}) & (NestedEnum) +MyEmptyInput: Record +(String): string +(String,): [string] +ExtraBracketsInTupleVariant: { A: string } +ExtraBracketsInUnnamedStruct: string +Vec: MyEnum[] +InlineTuple: { + demo: [string, boolean], +} +InlineTuple2: { + demo: [{ + demo: [string, boolean], +}, boolean], +} +Box: string +Box: string +SkippedFieldWithinVariant: { type: "A" } | { type: "B"; data: string } +KebabCase: { + "test-ing": string, +} +&[&str]: string[] +Issue281<'_>: { + default_unity_arguments: string[], +} +LifetimeGenericStruct<'_, i32>: { + borrowed: T[], + owned: T[], +} +LifetimeGenericEnum<'_, i32>: ({ Borrowed: T }) & { Owned?: never } | ({ Owned: T }) & { Borrowed?: never } +RenameWithWeirdCharsField: { + "@odata.context": string, +} +RenameWithWeirdCharsVariant: { "@odata.context": string } +RenamedFieldKeys: { + "": string, + "a\"b": string, + "a\\b": string, + "line\nbreak": string, + "line\u2028break": string, + "line\u2029break": string, +} +RenamedVariantWithSkippedPayload: "a-b" +type_type::Type: never +ActualType: { + a: GenericType, +} +SpectaTypeOverride: { + string_ident: string, + u32_ident: number, + path: string, + tuple: [string, number], +} +ContainerTypeOverrideStruct: string +ContainerTypeOverrideEnum: string +ContainerTypeOverrideGeneric>: string +ContainerTypeOverrideToGeneric: T +ContainerTypeOverrideTuple: [string, number] +ContainerTypeOverrideTupleGeneric: [T, string] +InvalidToValidType: { + cause: null, +} +TupleStruct: string +TupleStructWithRep: string +GenericTupleStruct: T +BracedStruct: string +Struct: { + t: "StructNew", + a: string, +} +Struct2: { + b: string, +} +Enum: { t: "A" } | { t: "B" } +Enum2: { t: "C" } | { t: "B" } | { t: "D"; enumField: null } +Enum3: { t: "A"; b: string } +StructRenameAllUppercase: { + A: number, + B: number, +} +RenameSerdeSpecialChar: { + "a/b": number, +} +EnumRenameAllUppercase: "HELLOWORLD" | "VARIANTB" | "TESTINGWORDS" +Recursive: { + demo: Recursive, +} +RecursiveMapValue: { + demo: { [key in string]: RecursiveMapValue }, +} +RecursiveTransparent: RecursiveInline +RecursiveInEnum: { A: { + demo: RecursiveInEnum, +} } +NonOptional: string | null +OptionalOnNamedField: string | null +OptionalOnTransparentNamedField: { + b: string | null, +} +OptionalInEnum: ({ A?: string | null }) & { B?: never; C?: never } | ({ B: { + a: string | null, +} }) & { A?: never; C?: never } | ({ C: { + a?: string | null, +} }) & { A?: never; B?: never } +UntaggedVariants: string | number | { id: string } | [string, boolean] +UntaggedVariantsWithoutValue: string | [number, string] | number +UntaggedVariantsWithDuplicateBranches: null | number +HashMap: { [key in string]: null } +Regular: { [key in string]: null } +HashMap: { [key in never]: null } +HashMap: { [key in TransparentStruct]: null } +HashMap: Partial<{ [key in UnitVariants]: null }> +HashMap: Partial<{ [key in UntaggedVariantsKey]: null }> +ValidMaybeValidKey: { [key in MaybeValidKey]: null } +ValidMaybeValidKeyNested: { [key in MaybeValidKey>]: null } +MacroStruct: string +MacroStruct2: { + demo: string, +} +MacroEnum: ({ Demo: string }) & { Demo2?: never } | ({ Demo2: { + demo2: string, +} }) & { Demo?: never } +DeprecatedType: { + a: number, +} +DeprecatedTypeWithMsg: { + a: number, +} +DeprecatedTypeWithMsg2: { + a: number, +} +DeprecatedFields: { + a: number, + /** + * @deprecated + */ + b: string, + /** + * @deprecated This field is cringe! + */ + c: string, + /** + * @deprecated This field is cringe! + */ + d: string, +} +DeprecatedTupleVariant: [ +/** + * @deprecated + */ +string, +/** + * @deprecated Nope + */ +string, +/** + * @deprecated Nope + */ +number] +DeprecatedEnumVariants: +/** + * @deprecated + */ +"A" | +/** + * @deprecated Nope + */ +"B" | +/** + * @deprecated Nope + */ +"C" +CommentedStruct: { + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + a: number, +} +CommentedEnum: +/** + * Some triple-slash comment + * Some more triple-slash comment + */ +({ A: number }) & { B?: never } | +/** + * Some triple-slash comment + * Some more triple-slash comment + */ +({ B: { + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + a: number, +} }) & { A?: never } +SingleLineComment: +/** Some single-line comment */ +({ A: number }) & { B?: never } | +/** Some single-line comment */ +({ B: { + /** Some single-line comment */ + a: number, +} }) & { A?: never } +NonGeneric: { + a: A, + b: B, +} +HalfGenericA: { + a: A, + b: B, +} +HalfGenericB: { + a: A, + b: B, +} +FullGeneric: { + a: A, + b: B, +} +Another: { + a: A, + b: B, +} +MapA: { [key in string]: number } +MapB: { [key in number]: string } +MapC: { [key in string]: AGenericStruct } +AGenericStruct: { + field: { + a: A, + b: B, +}, +} +A: { + a: B, + b: { + b: number, + }, + c: B, + d: { + flattened: number, + }, + e: { + generic_flattened: number, + }, +} +DoubleFlattened: { + a: ToBeFlattened, + b: ToBeFlattened, +} +FlattenedInner: (Inner) +BoxFlattened: (BoxedInner) +BoxInline: { + c: { + a: number, + }, +} +First: { + a: string, +} +Second: { + a: number, +} +Third: ({ + b: { [key in string]: string }, + c: First, +}) & (First) +Fourth: { + a: First, + b: { + a: string, + }, +} +TagOnStructWithInline: { + type: "TagOnStructWithInline", + a: First, + b: { + a: string, + }, +} +Sixth: { + a: First, + b: First, +} +Seventh: { + a: First, + b: Second, +} +Eight: { A: string } | "B" +Ninth: { t: "A"; c: string } | { t: "B" } | { t: "C"; c: { + a: string, +} } | { t: "D"; c: First } +Tenth: string | "B" | { + a: string, +} | First +MyEnumTagged: { + type: "Variant", +} & First +MyEnumExternal: { Variant: { + inner: First, +} } +MyEnumAdjacent: { t: "Variant"; c: { + inner: First, +} } +MyEnumUntagged: { inner: First } +EmptyStruct: Record +EmptyStructWithTag: { + a: "EmptyStructWithTag", +} +AdjacentlyTagged: { t: "A" } | { t: "B"; c: { + id: string, + method: string, +} } | { t: "C"; c: string } +LoadProjectEvent: { event: "started"; data: { + projectName: string, +} } | { event: "progressTest"; data: { + projectName: string, + status: string, + progress: number, +} } | { event: "finished"; data: { + projectName: string, +} } +ExternallyTagged: "A" | ({ B: { + id: string, + method: string, +} }) & { C?: never } | ({ C: string }) & { B?: never } +Issue221External: ({ A: { + a: string, +} }) & { B?: never } | ({ B: { + b: string, +} }) & { A?: never } +InternallyTaggedD: { + type: "A", +} & { [key in string]: string } +InternallyTaggedE: { type: "A" } +InternallyTaggedF: { type: "A" } +InternallyTaggedH: { type: "A" } +InternallyTaggedL: { + type: "A", +} & { type: "A" } | { type: "B" } +InternallyTaggedM: { type: "A" } +Issue221UntaggedSafe: ({ a: string }) & { b?: never } | ({ b: string }) & { a?: never } +Issue221UntaggedMixed: ({ a: string }) & { b?: never; values?: never } | ({ b: string }) & { a?: never; values?: never } | ({ values: { [key in string]: string } }) & { a?: never; b?: never } +EmptyEnum: never +EmptyEnumTagged: never +EmptyEnumTaggedWContent: never +EmptyEnumUntagged: never +SkipOnlyField: Record +SkipField: { + b: number, +} +SkipVariant: { A: string } +SkipUnnamedFieldInVariant: "A" | { B: [number] } +SkipNamedFieldInVariant: ({ A: Record }) & { B?: never } | ({ B: { + b: number, +} }) & { A?: never } +TransparentWithSkip: null +TransparentWithSkip2: string +TransparentWithSkip3: string +SkipVariant2: { tag: "A"; data: string } +SkipVariant3: { A: { + a: string, +} } +SkipStructFields: { + a: number, +} +SpectaSkipNonTypeField: { + a: number, +} +FlattenA: { + a: number, + b: number, +} +FlattenB: ({ + c: number, +}) & (FlattenA) +FlattenC: ({ + c: number, +}) & (FlattenA) +FlattenD: { + a: FlattenA, + c: number, +} +FlattenE: { + b: ({ + c: number, + }) & (FlattenA), + d: number, +} +FlattenF: { + b: ({ + c: number, + }) & (FlattenA), + d: number, +} +FlattenG: { + b: FlattenB, + d: number, +} +TupleNested: [number[], [number[], number[]], [number[], number[], number[]]] +Generic1<()>: { + value: T, + values: T[], +} +GenericAutoBound<()>: { + value: T, + values: T[], +} +GenericAutoBound2<()>: { + value: T, + values: T[], +} +Container1: { + foo: Generic1, + bar: Generic1[], + baz: { [key in string]: Generic1 }, +} +Generic2<(), String, i32>: ({ A: A }) & { B?: never; C?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ B: [B, B, B] }) & { A?: never; C?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ C: C[] }) & { A?: never; B?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ D: A[][][] }) & { A?: never; B?: never; C?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ E: { + a: A, + b: B, + c: C, +} }) & { A?: never; B?: never; C?: never; D?: never; X?: never; Y?: never; Z?: never } | ({ X: number[] }) & { A?: never; B?: never; C?: never; D?: never; E?: never; Y?: never; Z?: never } | ({ Y: number }) & { A?: never; B?: never; C?: never; D?: never; E?: never; X?: never; Z?: never } | ({ Z: number[][] }) & { A?: never; B?: never; C?: never; D?: never; E?: never; X?: never; Y?: never } +GenericNewType1<()>: T[][] +GenericTuple<()>: [T, T[], T[][]] +GenericStruct2<()>: { + a: T, + b: [T, T], + c: [T, [T, T]], + d: [T, T, T], + e: [([T, T]), ([T, T]), ([T, T])], + f: T[], + g: T[][], + h: ([([T, T]), ([T, T]), ([T, T])])[], +} +InlineGenericNewtype: string +InlineGenericNested: [string, string[], [string, string], { [key in string]: string }, string | null, "Unit" | ({ Unnamed: string }) & { Named?: never } | ({ Named: { + value: string, +} }) & { Unnamed?: never }] +InlineFlattenGenericsG<()>: { + t: T, +} +InlineFlattenGenerics: ({ + g: InlineFlattenGenericsG, + gi: { + t: string, + }, +}) & (InlineFlattenGenericsG) +GenericDefault: { + value: T, +} +ChainedGenericDefault: { + first: T, + second: U, +} +ChainedGenericDefault: { + first: T, + second: U, +} +ChainedGenericDefault: { + first: T, + second: U, +} +ChainedGenericDefault: { + first: T, + second: U, +} +GenericDefaultSkipped: { + value: T, +} +GenericDefaultSkippedNonType: { + value: number, +} +GenericParameterOrderPreserved: { + pair: Pair, +} +ConstGenericInNonConstContainer: { + data: [number], + a: [number, number], + d: [number, number], +} +ConstGenericInConstContainer: { + data: number[], + a: number[], + d: [number, number], +} +NamedConstGenericContainer: { + a: NamedConstGeneric, + b: NamedConstGeneric, + d: [number, number], +} +InlineConstGenericContainer: { + b: { + data: [number, number], + a: [number, number], + d: [number, number, number], + }, + c: { + data: [number, number, number], + a: [number, number], + d: [number, number, number], + }, + d: [number, number], +} +InlineRecursiveConstGenericContainer: { + b: { + data: [number, number], + a: [number, number], + d: [number, number, number], + e: InlineRecursiveConstGeneric, + }, + c: { + data: [number, number, number], + a: [number, number], + d: [number, number, number], + e: InlineRecursiveConstGeneric, + }, + d: [number, number], +} +TestCollectionRegister: never +TestCollectionRegister: never +specta_typescript::Any: any +specta_typescript::Any: any +specta_typescript::Unknown: unknown +specta_typescript::Unknown: unknown +specta_typescript::Never: never +specta_typescript::Never: never +specta_typescript::Number: number +specta_typescript::Number: number +specta_typescript::BigInt: bigint +specta_typescript::BigInt: bigint diff --git a/tests/tests/snapshots/test__typescript__ts-export-serde.snap b/tests/tests/snapshots/test__typescript__ts-export-serde.snap index f5e06f5b..2a0f99a8 100644 --- a/tests/tests/snapshots/test__typescript__ts-export-serde.snap +++ b/tests/tests/snapshots/test__typescript__ts-export-serde.snap @@ -1,5 +1,6 @@ --- source: tests/tests/typescript.rs +assertion_line: 95 expression: "Typescript::default().export(&types, format).unwrap()" --- // This file has been generated by Specta. Do not edit this file manually. @@ -538,7 +539,9 @@ export type MyEnumExternal = { Variant: { inner: First, } }; -export type MyEnumTagged = { type: "Variant"; inner: First }; +export type MyEnumTagged = { + type: "Variant", +} & First; export type MyEnumUntagged = { inner: First }; diff --git a/tests/tests/snapshots/test__typescript__ts-export-serde_phases.snap b/tests/tests/snapshots/test__typescript__ts-export-serde_phases.snap index bbd5bd23..5efd92dc 100644 --- a/tests/tests/snapshots/test__typescript__ts-export-serde_phases.snap +++ b/tests/tests/snapshots/test__typescript__ts-export-serde_phases.snap @@ -511,16 +511,13 @@ export type InternallyTaggedMInner = "A" | "B"; export type InternallyTaggedWithAlias = InternallyTaggedWithAlias_Serialize | InternallyTaggedWithAlias_Deserialize; -export type InternallyTaggedWithAlias_Deserialize = ({ A: { +export type InternallyTaggedWithAlias_Deserialize = { type: "A", } & { field: string, } | { bruh: string, -} }) & { B?: never } | ({ B: { - type: "B", - other: number, -} }) & { A?: never }; +} | { type: "B"; other: number }; export type InternallyTaggedWithAlias_Serialize = ({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }; @@ -602,7 +599,9 @@ export type MyEnumExternal = { Variant: { inner: First, } }; -export type MyEnumTagged = { type: "Variant"; inner: First }; +export type MyEnumTagged = { + type: "Variant", +} & First; export type MyEnumUntagged = { inner: First }; @@ -650,7 +649,7 @@ export type Optional_Deserialize = { export type Optional_Serialize = { a: number | null, b?: number | null, - c?: string | null, + c?: string, d: boolean, }; diff --git a/tests/tests/snapshots/test__typescript__ts-export-serde_phases.snap.new b/tests/tests/snapshots/test__typescript__ts-export-serde_phases.snap.new new file mode 100644 index 00000000..ae482da7 --- /dev/null +++ b/tests/tests/snapshots/test__typescript__ts-export-serde_phases.snap.new @@ -0,0 +1,1210 @@ +--- +source: tests/tests/typescript.rs +assertion_line: 95 +expression: "Typescript::default().export(&types, format).unwrap()" +--- +// This file has been generated by Specta. Do not edit this file manually. +export type A = { + a: B, + b: { + b: number, + }, + c: B, + d: { + flattened: number, + }, + e: { + generic_flattened: number, + }, +}; + +export type AGenericStruct = { + field: Demo, +}; + +export type ActualType = { + a: GenericType, +}; + +export type AdjacentlyTagged = { t: "A" } | { t: "B"; c: { + id: string, + method: string, +} } | { t: "C"; c: string }; + +export type AdjacentlyTaggedWithAlias = AdjacentlyTaggedWithAlias_Serialize | AdjacentlyTaggedWithAlias_Deserialize; + +export type AdjacentlyTaggedWithAlias_Deserialize = { type: "A"; data: { + field: string, +} | { + bruh: string, +} } | { type: "B"; data: { + other: number, +} }; + +export type AdjacentlyTaggedWithAlias_Serialize = { type: "A"; data: { + field: string, +} } | { type: "B"; data: { + other: number, +} }; + +export type B = { + b: number, +}; + +export type BasicEnum = "A" | "B"; + +export type BoxFlattened = BoxedInner; + +export type BoxInline = { + c: { + a: number, + }, +}; + +export type BoxedInner = { + a: number, +}; + +export type BracedStruct = string; + +export type ChainedGenericDefault = { + first: T, + second: U, +}; + +/** + * Some triple-slash comment + * Some more triple-slash comment + */ +export type CommentedEnum = +/** + * Some triple-slash comment + * Some more triple-slash comment + */ +({ A: number }) & { B?: never } | +/** + * Some triple-slash comment + * Some more triple-slash comment + */ +({ B: { + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + a: number, +} }) & { A?: never }; + +/** + * Some triple-slash comment + * Some more triple-slash comment + */ +export type CommentedStruct = { + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + a: number, +}; + +export type ConstGenericInConstContainer = { + data: number[], + a: number[], + d: [number, number], +}; + +export type ConstGenericInNonConstContainer = { + data: [number], + a: [number, number], + d: [number, number], +}; + +export type Container1 = { + foo: Generic1, + bar: Generic1[], + baz: { [key in string]: Generic1 }, +}; + +export type ContainerTypeOverrideEnum = string; + +export type ContainerTypeOverrideGeneric = string; + +export type ContainerTypeOverrideStruct = string; + +export type ContainerTypeOverrideToGeneric = T; + +export type ContainerTypeOverrideTuple = [string, number]; + +export type ContainerTypeOverrideTupleGeneric = [T, string]; + +export type D = { + flattened: number, +}; + +export type Demo = { + a: A, + b: B, +}; + +export type DeprecatedEnumVariants = +/** + * @deprecated + */ +"A" | +/** + * @deprecated Nope + */ +"B" | +/** + * @deprecated Nope + */ +"C"; + +export type DeprecatedFields = { + a: number, + /** + * @deprecated + */ + b: string, + /** + * @deprecated This field is cringe! + */ + c: string, + /** + * @deprecated This field is cringe! + */ + d: string, +}; + +export type DeprecatedTupleVariant = [ +/** + * @deprecated + */ +string, +/** + * @deprecated Nope + */ +string, +/** + * @deprecated Nope + */ +number]; + +/** + * @deprecated + */ +export type DeprecatedType = { + a: number, +}; + +/** + * @deprecated Look at you big man using a deprecation message + */ +export type DeprecatedTypeWithMsg = { + a: number, +}; + +/** + * @deprecated Look at you big man using a deprecation message + */ +export type DeprecatedTypeWithMsg2 = { + a: number, +}; + +export type DoubleFlattened = { + a: ToBeFlattened, + b: ToBeFlattened, +}; + +export type Eight = { A: string } | "B"; + +export type EmptyEnum = never; + +export type EmptyEnumTagged = never; + +export type EmptyEnumTaggedWContent = never; + +export type EmptyEnumUntagged = never; + +export type EmptyStruct = Record; + +export type EmptyStructWithTag = { + a: "EmptyStructWithTag", +}; + +export type Enum = { t: "A" } | { t: "B" }; + +export type Enum2 = { t: "C" } | { t: "B" } | { t: "D"; enumField: null }; + +export type Enum3 = { t: "A"; b: string }; + +export type EnumMacroAttributes = ({ A: string }) & { D?: never; bbb?: never; cccc?: never } | ({ bbb: number }) & { A?: never; D?: never; cccc?: never } | ({ cccc: number }) & { A?: never; D?: never; bbb?: never } | ({ D: { + a: string, + bbbbbb: number, +} }) & { A?: never; bbb?: never; cccc?: never }; + +export type EnumReferenceRecordKey = { + a: Partial<{ [key in BasicEnum]: number }>, +}; + +export type EnumRenameAllUppercase = "HELLOWORLD" | "VARIANTB" | "TESTINGWORDS"; + +export type EnumWithMultipleVariantAliases = EnumWithMultipleVariantAliases_Serialize | EnumWithMultipleVariantAliases_Deserialize; + +export type EnumWithMultipleVariantAliases_Deserialize = "Variant" | "bruh" | "alternative" | "Other"; + +export type EnumWithMultipleVariantAliases_Serialize = "Variant" | "Other"; + +export type EnumWithVariantAlias = EnumWithVariantAlias_Serialize | EnumWithVariantAlias_Deserialize; + +export type EnumWithVariantAliasAndRename = EnumWithVariantAliasAndRename_Serialize | EnumWithVariantAliasAndRename_Deserialize; + +export type EnumWithVariantAliasAndRename_Deserialize = "renamed_variant" | "bruh" | "Other"; + +export type EnumWithVariantAliasAndRename_Serialize = "renamed_variant" | "Other"; + +export type EnumWithVariantAlias_Deserialize = "Variant" | "bruh" | "Other"; + +export type EnumWithVariantAlias_Serialize = "Variant" | "Other"; + +export type ExternallyTagged = "A" | ({ B: { + id: string, + method: string, +} }) & { C?: never } | ({ C: string }) & { B?: never }; + +export type ExtraBracketsInTupleVariant = { A: string }; + +export type ExtraBracketsInUnnamedStruct = string; + +export type First = { + a: string, +}; + +export type FlattenA = { + a: number, + b: number, +}; + +export type FlattenB = { + c: number, +} & FlattenA; + +export type FlattenC = { + c: number, +} & FlattenA; + +export type FlattenD = { + a: FlattenA, + c: number, +}; + +export type FlattenE = { + b: ({ + c: number, + }) & (FlattenA), + d: number, +}; + +export type FlattenEnum = { tag: "One" } | { tag: "Two" } | { tag: "Three" }; + +export type FlattenEnumStruct = { + outer: string, +} & FlattenEnum; + +export type FlattenF = { + b: ({ + c: number, + }) & (FlattenA), + d: number, +}; + +export type FlattenG = { + b: FlattenB, + d: number, +}; + +export type FlattenOnNestedEnum = { + id: string, +} & NestedEnum; + +export type FlattenedInner = Inner; + +export type Fourth = { + a: First, + b: { + a: string, + }, +}; + +export type Generic1 = { + value: T, + values: T[], +}; + +export type Generic2 = ({ A: A }) & { B?: never; C?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ B: [B, B, B] }) & { A?: never; C?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ C: C[] }) & { A?: never; B?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ D: A[][][] }) & { A?: never; B?: never; C?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ E: { + a: A, + b: B, + c: C, +} }) & { A?: never; B?: never; C?: never; D?: never; X?: never; Y?: never; Z?: never } | ({ X: number[] }) & { A?: never; B?: never; C?: never; D?: never; E?: never; Y?: never; Z?: never } | ({ Y: number }) & { A?: never; B?: never; C?: never; D?: never; E?: never; X?: never; Z?: never } | ({ Z: number[][] }) & { A?: never; B?: never; C?: never; D?: never; E?: never; X?: never; Y?: never }; + +export type GenericAutoBound = { + value: T, + values: T[], +}; + +export type GenericAutoBound2 = { + value: T, + values: T[], +}; + +export type GenericDefault = { + value: T, +}; + +export type GenericDefaultSkipped = { + value: T, +}; + +export type GenericDefaultSkippedNonType = { + value: number, +}; + +export type GenericFlattened = { + generic_flattened: T, +}; + +export type GenericNewType1 = T[][]; + +export type GenericParameterOrderPreserved = { + pair: Pair, +}; + +export type GenericStruct = { + arg: T, +}; + +export type GenericStruct2 = { + a: T, + b: [T, T], + c: [T, [T, T]], + d: [T, T, T], + e: [([T, T]), ([T, T]), ([T, T])], + f: T[], + g: T[][], + h: ([([T, T]), ([T, T]), ([T, T])])[], +}; + +export type GenericTuple = [T, T[], T[][]]; + +export type GenericTupleStruct = T; + +export type GenericType = "Undefined" | T; + +export type HasGenericAlias = { [key in number]: string }; + +export type InlineConstGenericContainer = { + b: { + data: [number, number], + a: [number, number], + d: [number, number, number], + }, + c: { + data: [number, number, number], + a: [number, number], + d: [number, number, number], + }, + d: [number, number], +}; + +export type InlineEnumField = { A: { + a: string, +} }; + +export type InlineFlattenGenerics = { + g: InlineFlattenGenericsG, + gi: { + t: string, + }, +} & InlineFlattenGenericsG; + +export type InlineFlattenGenericsG = { + t: T, +}; + +export type InlineOptionalType = { + optional_field: { + a: string, +} | null, +}; + +export type InlineRecursiveConstGeneric = { + data: number[], + a: number[], + d: [number, number, number], + e: InlineRecursiveConstGeneric, +}; + +export type InlineRecursiveConstGenericContainer = { + b: { + data: [number, number], + a: [number, number], + d: [number, number, number], + e: InlineRecursiveConstGeneric, + }, + c: { + data: [number, number, number], + a: [number, number], + d: [number, number, number], + e: InlineRecursiveConstGeneric, + }, + d: [number, number], +}; + +export type InlineStruct = { + ref_struct: SimpleStruct, + val: number, +}; + +export type InlineTuple = { + demo: [string, boolean], +}; + +export type InlineTuple2 = { + demo: [{ + demo: [string, boolean], +}, boolean], +}; + +export type InlinerStruct = { + inline_this: { + ref_struct: SimpleStruct, + val: number, + }, + dont_inline_this: RefStruct, +}; + +export type Inner = { + a: number, +} & FlattenedInner; + +export type InternallyTaggedD = { + type: "A", +} & { [key in string]: string }; + +export type InternallyTaggedE = { type: "A" }; + +export type InternallyTaggedF = { type: "A" }; + +export type InternallyTaggedFInner = null; + +export type InternallyTaggedH = { type: "A" }; + +export type InternallyTaggedHInner = null; + +export type InternallyTaggedL = { + type: "A", +} & { type: "A" } | { type: "B" }; + +export type InternallyTaggedLInner = { type: "A" } | { type: "B" }; + +export type InternallyTaggedM = { type: "A" }; + +export type InternallyTaggedMInner = "A" | "B"; + +export type InternallyTaggedWithAlias = InternallyTaggedWithAlias_Serialize | InternallyTaggedWithAlias_Deserialize; + +export type InternallyTaggedWithAlias_Deserialize = { + type: "A", +} & { + field: string, +} | { + bruh: string, +} | { type: "B"; other: number }; + +export type InternallyTaggedWithAlias_Serialize = ({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }; + +export type InvalidToValidType = { + cause: null, +}; + +export type Issue221External = ({ A: { + a: string, +} }) & { B?: never } | ({ B: { + b: string, +} }) & { A?: never }; + +export type Issue221UntaggedMixed = ({ a: string }) & { b?: never; values?: never } | ({ b: string }) & { a?: never; values?: never } | ({ values: { [key in string]: string } }) & { a?: never; b?: never }; + +export type Issue221UntaggedSafe = ({ a: string }) & { b?: never } | ({ b: string }) & { a?: never }; + +export type Issue281 = { + default_unity_arguments: string[], +}; + +/** https://github.com/specta-rs/specta/issues/374 */ +export type Issue374 = Issue374_Serialize | Issue374_Deserialize; + +/** https://github.com/specta-rs/specta/issues/374 */ +export type Issue374_Deserialize = { + foo?: boolean, + bar?: boolean, +}; + +/** https://github.com/specta-rs/specta/issues/374 */ +export type Issue374_Serialize = { + foo?: boolean, + bar?: boolean, +}; + +export type KebabCase = { + "test-ing": string, +}; + +export type LifetimeGenericEnum = ({ Borrowed: T }) & { Owned?: never } | ({ Owned: T }) & { Borrowed?: never }; + +export type LifetimeGenericStruct = { + borrowed: T[], + owned: T[], +}; + +export type LoadProjectEvent = { event: "started"; data: { + projectName: string, +} } | { event: "progressTest"; data: { + projectName: string, + status: string, + progress: number, +} } | { event: "finished"; data: { + projectName: string, +} }; + +export type MacroEnum = ({ Demo: string }) & { Demo2?: never } | ({ Demo2: { + demo2: string, +} }) & { Demo?: never }; + +export type MacroStruct = string; + +export type MacroStruct2 = { + demo: string, +}; + +export type MaybeValidKey = T; + +export type MyEmptyInput = Record; + +export type MyEnum = ({ A: string }) & { B?: never } | ({ B: number }) & { A?: never }; + +export type MyEnumAdjacent = { t: "Variant"; c: { + inner: First, +} }; + +export type MyEnumExternal = { Variant: { + inner: First, +} }; + +export type MyEnumTagged = { + type: "Variant", +} & First; + +export type MyEnumUntagged = { inner: First }; + +export type NamedConstGeneric = { + data: number[], + a: number[], + d: [number, number], +}; + +export type NamedConstGenericContainer = { + a: NamedConstGeneric, + b: NamedConstGeneric, + d: [number, number], +}; + +export type NestedEnum = { type: "a"; value: string } | { type: "b"; value: number }; + +export type Ninth = { t: "A"; c: string } | { t: "B" } | { t: "C"; c: { + a: string, +} } | { t: "D"; c: First }; + +export type NonOptional = string | null; + +export type Optional = Optional_Serialize | Optional_Deserialize; + +export type OptionalInEnum = ({ A?: string | null }) & { B?: never; C?: never } | ({ B: { + a: string | null, +} }) & { A?: never; C?: never } | ({ C: { + a?: string | null, +} }) & { A?: never; B?: never }; + +export type OptionalOnNamedField = string | null; + +export type OptionalOnTransparentNamedField = { + b: string | null, +}; + +export type Optional_Deserialize = { + a: number | null, + b?: number | null, + c: string | null, + d?: boolean, +}; + +export type Optional_Serialize = { + a: number | null, + b?: number | null, + c?: string, + d: boolean, +}; + +export type OverridenStruct = { + overriden_field: string, +}; + +export type Pair = { + first: Z, + second: A, +}; + +export type PlaceholderInnerField = { + a: string, +}; + +export type Primitives = { + i8: number, + i16: number, + i32: number, + u8: number, + u16: number, + u32: number, + f32: number | null, + f64: number | null, + bool: boolean, + char: string, + "Range": Range, + "RangeInclusive": RangeInclusive, + "()": null, + "(String, i32)": [string, number], + "(String, i32, bool)": [string, number, boolean], + "((String, i32), (bool, char, bool), ())": [[string, number], [boolean, string, boolean], null], + "(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)": [boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean], + "(Vec, Vec)": [number[], boolean[]], + String: string, + PathBuf: string, + IpAddr: string, + Ipv4Addr: string, + Ipv6Addr: string, + SocketAddr: string, + SocketAddrV4: string, + SocketAddrV6: string, + "Cow<'static, str>": string, + "Cow<'static, i32>": number, + "&'static str": string, + "&'static bool": boolean, + "&'static i32": number, + "Vec": number[], + "&'static [i32]": number[], + "&'static [i32; 3]": [number, number, number], + "[i32; 3]": [number, number, number], + "Vec": MyEnum[], + "&'static [MyEnum]": MyEnum[], + "&'static [MyEnum; 6]": [MyEnum, MyEnum, MyEnum, MyEnum, MyEnum, MyEnum], + "[MyEnum; 2]": [MyEnum, MyEnum], + "&'static [i32; 1]": [number], + "&'static [i32; 0]": [], + "Option": number | null, + "Option<()>": null, + "Option>": number[] | null, + "Result": Result, + "Vec>>": (number | null)[], + "Option>>": number[] | null, + "[Vec; 3]": [string[], string[], string[]], + "Option>": string | null, + "Option>>": string | null, + "PhantomData<()>": null, + "PhantomData": null, + Infallible: never, + Unit1: Unit1, + Unit2: Unit2, + Unit3: Unit3, + Unit4: Unit4, + Unit5: Unit5, + Unit6: Unit6, + Unit7: Unit7, + SimpleStruct: SimpleStruct, + TupleStruct1: TupleStruct1, + TupleStruct3: TupleStruct3, + TestEnum: TestEnum, + RefStruct: RefStruct, + InlinerStruct: InlinerStruct, + "GenericStruct": GenericStruct, + "GenericStruct": GenericStruct, + FlattenEnumStruct: FlattenEnumStruct, + OverridenStruct: OverridenStruct, + HasGenericAlias: HasGenericAlias, + EnumMacroAttributes: EnumMacroAttributes, + InlineEnumField: InlineEnumField, + InlineOptionalType: InlineOptionalType, + Rename: Rename, + TransparentType: TransparentType, + TransparentType2: TransparentType2, + TransparentTypeWithOverride: TransparentTypeWithOverride, + "[Option; 3]": [(number | null), (number | null), (number | null)], + "HashMap": Partial<{ [key in BasicEnum]: null }>, + "HashMap": Partial<{ [key in BasicEnum]: number }>, + "Option>>>": number | null, + "Vec": PlaceholderInnerField[], + EnumReferenceRecordKey: EnumReferenceRecordKey, + FlattenOnNestedEnum: FlattenOnNestedEnum, + MyEmptyInput: MyEmptyInput, + "(String)": string, + "(String,)": [string], + ExtraBracketsInTupleVariant: ExtraBracketsInTupleVariant, + ExtraBracketsInUnnamedStruct: ExtraBracketsInUnnamedStruct, + "Vec": MyEnum[], + InlineTuple: InlineTuple, + InlineTuple2: InlineTuple2, + "Box": string, + "Box": string, + SkippedFieldWithinVariant: SkippedFieldWithinVariant, + KebabCase: KebabCase, + "&[&str]": string[], + "Issue281<'_>": Issue281, + "LifetimeGenericStruct<'_, i32>": LifetimeGenericStruct, + "LifetimeGenericEnum<'_, i32>": LifetimeGenericEnum, + RenameWithWeirdCharsField: RenameWithWeirdCharsField, + RenameWithWeirdCharsVariant: RenameWithWeirdCharsVariant, + RenamedFieldKeys: RenamedFieldKeys, + RenamedVariantWithSkippedPayload: RenamedVariantWithSkippedPayload, + "type_type::Type": Type, + ActualType: ActualType, + SpectaTypeOverride: SpectaTypeOverride, + ContainerTypeOverrideStruct: ContainerTypeOverrideStruct, + ContainerTypeOverrideEnum: ContainerTypeOverrideEnum, + "ContainerTypeOverrideGeneric>": ContainerTypeOverrideGeneric, + "ContainerTypeOverrideToGeneric": ContainerTypeOverrideToGeneric, + ContainerTypeOverrideTuple: ContainerTypeOverrideTuple, + "ContainerTypeOverrideTupleGeneric": ContainerTypeOverrideTupleGeneric, + InvalidToValidType: InvalidToValidType, + TupleStruct: TupleStruct, + TupleStructWithRep: TupleStructWithRep, + "GenericTupleStruct": GenericTupleStruct, + BracedStruct: BracedStruct, + Struct: StructNew, + Struct2: Struct2, + Enum: Enum, + Enum2: Enum2, + Enum3: Enum3, + StructRenameAllUppercase: StructRenameAllUppercase, + RenameSerdeSpecialChar: RenameSerdeSpecialChar, + EnumRenameAllUppercase: EnumRenameAllUppercase, + Recursive: Recursive, + RecursiveMapValue: RecursiveMapValue, + RecursiveTransparent: RecursiveTransparent, + RecursiveInEnum: RecursiveInEnum, + NonOptional: NonOptional, + OptionalOnNamedField: OptionalOnNamedField, + OptionalOnTransparentNamedField: OptionalOnTransparentNamedField, + OptionalInEnum: OptionalInEnum, + UntaggedVariants: UntaggedVariants, + UntaggedVariantsWithoutValue: UntaggedVariantsWithoutValue, + UntaggedVariantsWithDuplicateBranches: UntaggedVariantsWithDuplicateBranches, + "HashMap": { [key in string]: null }, + Regular: Regular, + "HashMap": { [key in never]: null }, + "HashMap": { [key in TransparentStruct]: null }, + "HashMap": Partial<{ [key in UnitVariants]: null }>, + "HashMap": Partial<{ [key in UntaggedVariantsKey]: null }>, + ValidMaybeValidKey: ValidMaybeValidKey, + ValidMaybeValidKeyNested: ValidMaybeValidKeyNested, + MacroStruct: MacroStruct, + MacroStruct2: MacroStruct2, + MacroEnum: MacroEnum, + DeprecatedType: DeprecatedType, + DeprecatedTypeWithMsg: DeprecatedTypeWithMsg, + DeprecatedTypeWithMsg2: DeprecatedTypeWithMsg2, + DeprecatedFields: DeprecatedFields, + DeprecatedTupleVariant: DeprecatedTupleVariant, + DeprecatedEnumVariants: DeprecatedEnumVariants, + CommentedStruct: CommentedStruct, + CommentedEnum: CommentedEnum, + SingleLineComment: SingleLineComment, + NonGeneric: Demo, + "HalfGenericA": Demo, + "HalfGenericB": Demo, + "FullGeneric": Demo, + "Another": Demo, + "MapA": { [key in string]: number }, + "MapB": { [key in number]: string }, + "MapC": { [key in string]: AGenericStruct }, + "AGenericStruct": AGenericStruct, + A: A, + DoubleFlattened: DoubleFlattened, + FlattenedInner: FlattenedInner, + BoxFlattened: BoxFlattened, + BoxInline: BoxInline, + First: First, + Second: Second, + Third: Third, + Fourth: Fourth, + TagOnStructWithInline: TagOnStructWithInline, + Sixth: Sixth, + Seventh: Seventh, + Eight: Eight, + Ninth: Ninth, + Tenth: Tenth, + MyEnumTagged: MyEnumTagged, + MyEnumExternal: MyEnumExternal, + MyEnumAdjacent: MyEnumAdjacent, + MyEnumUntagged: MyEnumUntagged, + EmptyStruct: EmptyStruct, + EmptyStructWithTag: EmptyStructWithTag, + AdjacentlyTagged: AdjacentlyTagged, + LoadProjectEvent: LoadProjectEvent, + ExternallyTagged: ExternallyTagged, + Issue221External: Issue221External, + InternallyTaggedD: InternallyTaggedD, + InternallyTaggedE: InternallyTaggedE, + InternallyTaggedF: InternallyTaggedF, + InternallyTaggedH: InternallyTaggedH, + InternallyTaggedL: InternallyTaggedL, + InternallyTaggedM: InternallyTaggedM, + Issue221UntaggedSafe: Issue221UntaggedSafe, + Issue221UntaggedMixed: Issue221UntaggedMixed, + EmptyEnum: EmptyEnum, + EmptyEnumTagged: EmptyEnumTagged, + EmptyEnumTaggedWContent: EmptyEnumTaggedWContent, + EmptyEnumUntagged: EmptyEnumUntagged, + SkipOnlyField: SkipOnlyField, + SkipField: SkipField, + SkipVariant: SkipVariant, + SkipUnnamedFieldInVariant: SkipUnnamedFieldInVariant, + SkipNamedFieldInVariant: SkipNamedFieldInVariant, + TransparentWithSkip: TransparentWithSkip, + TransparentWithSkip2: TransparentWithSkip2, + TransparentWithSkip3: TransparentWithSkip3, + SkipVariant2: SkipVariant2, + SkipVariant3: SkipVariant3, + SkipStructFields: SkipStructFields, + SpectaSkipNonTypeField: SpectaSkipNonTypeField, + FlattenA: FlattenA, + FlattenB: FlattenB, + FlattenC: FlattenC, + FlattenD: FlattenD, + FlattenE: FlattenE, + FlattenF: FlattenF, + FlattenG: FlattenG, + TupleNested: TupleNested, + "Generic1<()>": Generic1, + "GenericAutoBound<()>": GenericAutoBound, + "GenericAutoBound2<()>": GenericAutoBound2, + Container1: Container1, + "Generic2<(), String, i32>": Generic2, + "GenericNewType1<()>": GenericNewType1, + "GenericTuple<()>": GenericTuple, + "GenericStruct2<()>": GenericStruct2, + "InlineGenericNewtype": string, + "InlineGenericNested": [string, string[], [string, string], { [key in string]: string }, string | null, "Unit" | ({ Unnamed: string }) & { Named?: never } | ({ Named: { + value: string, +} }) & { Unnamed?: never }], + "InlineFlattenGenericsG<()>": InlineFlattenGenericsG, + InlineFlattenGenerics: InlineFlattenGenerics, + GenericDefault: GenericDefault, + ChainedGenericDefault: ChainedGenericDefault, + "ChainedGenericDefault": ChainedGenericDefault, + "ChainedGenericDefault": ChainedGenericDefault, + "ChainedGenericDefault": ChainedGenericDefault, + GenericDefaultSkipped: GenericDefaultSkipped, + GenericDefaultSkippedNonType: GenericDefaultSkippedNonType, + GenericParameterOrderPreserved: GenericParameterOrderPreserved, + ConstGenericInNonConstContainer: ConstGenericInNonConstContainer, + ConstGenericInConstContainer: ConstGenericInConstContainer, + NamedConstGenericContainer: NamedConstGenericContainer, + InlineConstGenericContainer: InlineConstGenericContainer, + InlineRecursiveConstGenericContainer: InlineRecursiveConstGenericContainer, + TestCollectionRegister: TestCollectionRegister, + TestCollectionRegister: TestCollectionRegister, +}; + +export type Range = { + start: T, + end: T, +}; + +export type RangeInclusive = { + start: T, + end: T, +}; + +export type Recursive = { + demo: Recursive, +}; + +export type RecursiveInEnum = { A: { + demo: RecursiveInEnum, +} }; + +export type RecursiveInline = RecursiveInline; + +export type RecursiveMapValue = { + demo: { [key in string]: RecursiveMapValue }, +}; + +export type RecursiveTransparent = RecursiveInline; + +export type RefStruct = TestEnum; + +export type Regular = { [key in string]: null }; + +export type Rename = "OneWord" | "Two words"; + +export type RenameSerdeSpecialChar = { + "a/b": number, +}; + +export type RenameWithWeirdCharsField = { + "@odata.context": string, +}; + +export type RenameWithWeirdCharsVariant = { "@odata.context": string }; + +export type RenamedFieldKeys = { + "": string, + "a\"b": string, + "a\\b": string, + "line\nbreak": string, + "line\u2028break": string, + "line\u2029break": string, +}; + +export type RenamedVariantWithSkippedPayload = "a-b"; + +export type Result = { + ok: T, + err: E, +}; + +export type Second = { + a: number, +}; + +export type Seventh = { + a: First, + b: Second, +}; + +export type SimpleStruct = { + a: number, + b: string, + c: [number, string, number], + d: string[], + e: string | null, +}; + +/** Some single-line comment */ +export type SingleLineComment = +/** Some single-line comment */ +({ A: number }) & { B?: never } | +/** Some single-line comment */ +({ B: { + /** Some single-line comment */ + a: number, +} }) & { A?: never }; + +export type Sixth = { + a: First, + b: First, +}; + +export type SkipField = { + b: number, +}; + +export type SkipNamedFieldInVariant = ({ A: Record }) & { B?: never } | ({ B: { + b: number, +} }) & { A?: never }; + +export type SkipOnlyField = Record; + +export type SkipStructFields = { + a: number, +}; + +export type SkipUnnamedFieldInVariant = "A" | { B: [number] }; + +export type SkipVariant = { A: string }; + +export type SkipVariant2 = { tag: "A"; data: string }; + +export type SkipVariant3 = { A: { + a: string, +} }; + +export type SkippedFieldWithinVariant = { type: "A" } | { type: "B"; data: string }; + +export type SpectaSkipNonTypeField = { + a: number, +}; + +export type SpectaTypeOverride = { + string_ident: string, + u32_ident: number, + path: string, + tuple: [string, number], +}; + +export type Struct2 = { + b: string, +}; + +export type StructNew = { + t: "StructNew", + a: string, +}; + +export type StructPhaseSpecificRename = StructPhaseSpecificRenameSerialize | StructPhaseSpecificRenameDeserialize; + +export type StructPhaseSpecificRenameDeserialize = { + kind: "StructPhaseSpecificRenameDeserialize", + der: string, +}; + +export type StructPhaseSpecificRenameSerialize = { + kind: "StructPhaseSpecificRenameSerialize", + ser: string, +}; + +export type StructRenameAllUppercase = { + A: number, + B: number, +}; + +export type StructWithAlias = StructWithAlias_Serialize | StructWithAlias_Deserialize; + +export type StructWithAliasAndRename = StructWithAliasAndRename_Serialize | StructWithAliasAndRename_Deserialize; + +export type StructWithAliasAndRename_Deserialize = { + renamed_field: string, +}; + +export type StructWithAliasAndRename_Serialize = { + renamed_field: string, +}; + +export type StructWithAlias_Deserialize = { + field: string, +} | { + bruh: string, +}; + +export type StructWithAlias_Serialize = { + field: string, +}; + +export type StructWithMultipleAliases = StructWithMultipleAliases_Serialize | StructWithMultipleAliases_Deserialize; + +export type StructWithMultipleAliases_Deserialize = { + field: string, +} | { + bruh: string, +} | { + alternative: string, +} | { + another: string, +}; + +export type StructWithMultipleAliases_Serialize = { + field: string, +}; + +export type TagOnStructWithInline = { + type: "TagOnStructWithInline", + a: First, + b: { + a: string, + }, +}; + +export type Tenth = string | "B" | { + a: string, +} | First; + +export type TestCollectionRegister = never; + +export type TestEnum = "Unit" | ({ Single: number }) & { Multiple?: never; Struct?: never } | ({ Multiple: [number, number] }) & { Single?: never; Struct?: never } | ({ Struct: { + a: number, +} }) & { Multiple?: never; Single?: never }; + +export type Third = { + b: { [key in string]: string }, + c: First, +} & First; + +export type ToBeFlattened = { + a: string, +}; + +export type TransparentStruct = string; + +export type TransparentType = TransparentTypeInner; + +export type TransparentType2 = null; + +export type TransparentTypeInner = { + inner: string, +}; + +export type TransparentTypeWithOverride = string; + +export type TransparentWithSkip = null; + +export type TransparentWithSkip2 = string; + +export type TransparentWithSkip3 = string; + +export type TupleNested = [number[], [number[], number[]], [number[], number[], number[]]]; + +export type TupleStruct = string; + +export type TupleStruct1 = number; + +export type TupleStruct3 = [number, boolean, string]; + +export type TupleStructWithRep = string; + +export type Type = never; + +export type Unit1 = null; + +export type Unit2 = Record; + +export type Unit3 = []; + +export type Unit4 = null; + +export type Unit5 = "A"; + +export type Unit6 = { A: null }; + +export type Unit7 = { A: Record }; + +export type UnitVariants = "A" | "B" | "C"; + +export type UntaggedVariants = string | number | { id: string } | [string, boolean]; + +export type UntaggedVariantsKey = string | number; + +export type UntaggedVariantsWithDuplicateBranches = null | number; + +export type UntaggedVariantsWithoutValue = string | [number, string] | number; + +export type UntaggedWithAlias = UntaggedWithAlias_Serialize | UntaggedWithAlias_Deserialize; + +export type UntaggedWithAlias_Deserialize = { + field: string, +} | { + bruh: string, +} | { other: number }; + +export type UntaggedWithAlias_Serialize = ({ field: string }) & { other?: never } | ({ other: number }) & { field?: never }; + +export type ValidMaybeValidKey = { [key in MaybeValidKey]: null }; + +export type ValidMaybeValidKeyNested = { [key in MaybeValidKey>]: null }; diff --git a/tests/tests/snapshots/test__typescript__ts-export-to-files-serde.snap b/tests/tests/snapshots/test__typescript__ts-export-to-files-serde.snap index 8fa98f8d..56ed2297 100644 --- a/tests/tests/snapshots/test__typescript__ts-export-to-files-serde.snap +++ b/tests/tests/snapshots/test__typescript__ts-export-to-files-serde.snap @@ -1,5 +1,6 @@ --- source: tests/tests/typescript.rs +assertion_line: 946 expression: output --- std/ @@ -34,7 +35,7 @@ test/ export type Type = never; ════════════════════════════════════════ - types.ts (15641 bytes) + types.ts (15637 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. export type A = { @@ -572,7 +573,9 @@ test/ inner: First, } }; - export type MyEnumTagged = { type: "Variant"; inner: First }; + export type MyEnumTagged = { + type: "Variant", + } & First; export type MyEnumUntagged = { inner: First }; diff --git a/tests/tests/snapshots/test__typescript__ts-export-to-files-serde_phases.snap b/tests/tests/snapshots/test__typescript__ts-export-to-files-serde_phases.snap index c7712bd3..008aded0 100644 --- a/tests/tests/snapshots/test__typescript__ts-export-to-files-serde_phases.snap +++ b/tests/tests/snapshots/test__typescript__ts-export-to-files-serde_phases.snap @@ -34,7 +34,7 @@ test/ export type Type = never; ════════════════════════════════════════ - types.ts (19585 bytes) + types.ts (19521 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. export type A = { @@ -545,16 +545,13 @@ test/ export type InternallyTaggedWithAlias = InternallyTaggedWithAlias_Serialize | InternallyTaggedWithAlias_Deserialize; - export type InternallyTaggedWithAlias_Deserialize = ({ A: { + export type InternallyTaggedWithAlias_Deserialize = { type: "A", } & { field: string, } | { bruh: string, - } }) & { B?: never } | ({ B: { - type: "B", - other: number, - } }) & { A?: never }; + } | { type: "B"; other: number }; export type InternallyTaggedWithAlias_Serialize = ({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }; @@ -636,7 +633,9 @@ test/ inner: First, } }; - export type MyEnumTagged = { type: "Variant"; inner: First }; + export type MyEnumTagged = { + type: "Variant", + } & First; export type MyEnumUntagged = { inner: First }; @@ -684,7 +683,7 @@ test/ export type Optional_Serialize = { a: number | null, b?: number | null, - c?: string | null, + c?: string, d: boolean, }; diff --git a/tests/tests/snapshots/test__typescript__ts-export-to-files-serde_phases.snap.new b/tests/tests/snapshots/test__typescript__ts-export-to-files-serde_phases.snap.new new file mode 100644 index 00000000..8b008b39 --- /dev/null +++ b/tests/tests/snapshots/test__typescript__ts-export-to-files-serde_phases.snap.new @@ -0,0 +1,1239 @@ +--- +source: tests/tests/typescript.rs +assertion_line: 946 +expression: output +--- +std/ + ops.ts (181 bytes) + ──────────────────────────────────────── + // This file has been generated by Specta. Do not edit this file manually. + export type Range = { + start: T, + end: T, + }; + + export type RangeInclusive = { + start: T, + end: T, + }; + ════════════════════════════════════════ + + result.ts (124 bytes) + ──────────────────────────────────────── + // This file has been generated by Specta. Do not edit this file manually. + export type Result = { + ok: T, + err: E, + }; + ════════════════════════════════════════ + +test/ + types/ + type_type.ts (101 bytes) + ──────────────────────────────────────── + // This file has been generated by Specta. Do not edit this file manually. + export type Type = never; + ════════════════════════════════════════ + + types.ts (19521 bytes) + ──────────────────────────────────────── + // This file has been generated by Specta. Do not edit this file manually. + export type A = { + a: B, + b: { + b: number, + }, + c: B, + d: { + flattened: number, + }, + e: { + generic_flattened: number, + }, + }; + + export type AGenericStruct = { + field: Demo, + }; + + export type ActualType = { + a: GenericType, + }; + + export type AdjacentlyTagged = { t: "A" } | { t: "B"; c: { + id: string, + method: string, + } } | { t: "C"; c: string }; + + export type AdjacentlyTaggedWithAlias = AdjacentlyTaggedWithAlias_Serialize | AdjacentlyTaggedWithAlias_Deserialize; + + export type AdjacentlyTaggedWithAlias_Deserialize = { type: "A"; data: { + field: string, + } | { + bruh: string, + } } | { type: "B"; data: { + other: number, + } }; + + export type AdjacentlyTaggedWithAlias_Serialize = { type: "A"; data: { + field: string, + } } | { type: "B"; data: { + other: number, + } }; + + export type B = { + b: number, + }; + + export type BasicEnum = "A" | "B"; + + export type BoxFlattened = BoxedInner; + + export type BoxInline = { + c: { + a: number, + }, + }; + + export type BoxedInner = { + a: number, + }; + + export type BracedStruct = string; + + export type ChainedGenericDefault = { + first: T, + second: U, + }; + + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + export type CommentedEnum = + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + ({ A: number }) & { B?: never } | + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + ({ B: { + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + a: number, + } }) & { A?: never }; + + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + export type CommentedStruct = { + /** + * Some triple-slash comment + * Some more triple-slash comment + */ + a: number, + }; + + export type ConstGenericInConstContainer = { + data: number[], + a: number[], + d: [number, number], + }; + + export type ConstGenericInNonConstContainer = { + data: [number], + a: [number, number], + d: [number, number], + }; + + export type Container1 = { + foo: Generic1, + bar: Generic1[], + baz: { [key in string]: Generic1 }, + }; + + export type ContainerTypeOverrideEnum = string; + + export type ContainerTypeOverrideGeneric = string; + + export type ContainerTypeOverrideStruct = string; + + export type ContainerTypeOverrideToGeneric = T; + + export type ContainerTypeOverrideTuple = [string, number]; + + export type ContainerTypeOverrideTupleGeneric = [T, string]; + + export type D = { + flattened: number, + }; + + export type Demo = { + a: A, + b: B, + }; + + export type DeprecatedEnumVariants = + /** + * @deprecated + */ + "A" | + /** + * @deprecated Nope + */ + "B" | + /** + * @deprecated Nope + */ + "C"; + + export type DeprecatedFields = { + a: number, + /** + * @deprecated + */ + b: string, + /** + * @deprecated This field is cringe! + */ + c: string, + /** + * @deprecated This field is cringe! + */ + d: string, + }; + + export type DeprecatedTupleVariant = [ + /** + * @deprecated + */ + string, + /** + * @deprecated Nope + */ + string, + /** + * @deprecated Nope + */ + number]; + + /** + * @deprecated + */ + export type DeprecatedType = { + a: number, + }; + + /** + * @deprecated Look at you big man using a deprecation message + */ + export type DeprecatedTypeWithMsg = { + a: number, + }; + + /** + * @deprecated Look at you big man using a deprecation message + */ + export type DeprecatedTypeWithMsg2 = { + a: number, + }; + + export type DoubleFlattened = { + a: ToBeFlattened, + b: ToBeFlattened, + }; + + export type Eight = { A: string } | "B"; + + export type EmptyEnum = never; + + export type EmptyEnumTagged = never; + + export type EmptyEnumTaggedWContent = never; + + export type EmptyEnumUntagged = never; + + export type EmptyStruct = Record; + + export type EmptyStructWithTag = { + a: "EmptyStructWithTag", + }; + + export type Enum = { t: "A" } | { t: "B" }; + + export type Enum2 = { t: "C" } | { t: "B" } | { t: "D"; enumField: null }; + + export type Enum3 = { t: "A"; b: string }; + + export type EnumMacroAttributes = ({ A: string }) & { D?: never; bbb?: never; cccc?: never } | ({ bbb: number }) & { A?: never; D?: never; cccc?: never } | ({ cccc: number }) & { A?: never; D?: never; bbb?: never } | ({ D: { + a: string, + bbbbbb: number, + } }) & { A?: never; bbb?: never; cccc?: never }; + + export type EnumReferenceRecordKey = { + a: Partial<{ [key in BasicEnum]: number }>, + }; + + export type EnumRenameAllUppercase = "HELLOWORLD" | "VARIANTB" | "TESTINGWORDS"; + + export type EnumWithMultipleVariantAliases = EnumWithMultipleVariantAliases_Serialize | EnumWithMultipleVariantAliases_Deserialize; + + export type EnumWithMultipleVariantAliases_Deserialize = "Variant" | "bruh" | "alternative" | "Other"; + + export type EnumWithMultipleVariantAliases_Serialize = "Variant" | "Other"; + + export type EnumWithVariantAlias = EnumWithVariantAlias_Serialize | EnumWithVariantAlias_Deserialize; + + export type EnumWithVariantAliasAndRename = EnumWithVariantAliasAndRename_Serialize | EnumWithVariantAliasAndRename_Deserialize; + + export type EnumWithVariantAliasAndRename_Deserialize = "renamed_variant" | "bruh" | "Other"; + + export type EnumWithVariantAliasAndRename_Serialize = "renamed_variant" | "Other"; + + export type EnumWithVariantAlias_Deserialize = "Variant" | "bruh" | "Other"; + + export type EnumWithVariantAlias_Serialize = "Variant" | "Other"; + + export type ExternallyTagged = "A" | ({ B: { + id: string, + method: string, + } }) & { C?: never } | ({ C: string }) & { B?: never }; + + export type ExtraBracketsInTupleVariant = { A: string }; + + export type ExtraBracketsInUnnamedStruct = string; + + export type First = { + a: string, + }; + + export type FlattenA = { + a: number, + b: number, + }; + + export type FlattenB = { + c: number, + } & FlattenA; + + export type FlattenC = { + c: number, + } & FlattenA; + + export type FlattenD = { + a: FlattenA, + c: number, + }; + + export type FlattenE = { + b: ({ + c: number, + }) & (FlattenA), + d: number, + }; + + export type FlattenEnum = { tag: "One" } | { tag: "Two" } | { tag: "Three" }; + + export type FlattenEnumStruct = { + outer: string, + } & FlattenEnum; + + export type FlattenF = { + b: ({ + c: number, + }) & (FlattenA), + d: number, + }; + + export type FlattenG = { + b: FlattenB, + d: number, + }; + + export type FlattenOnNestedEnum = { + id: string, + } & NestedEnum; + + export type FlattenedInner = Inner; + + export type Fourth = { + a: First, + b: { + a: string, + }, + }; + + export type Generic1 = { + value: T, + values: T[], + }; + + export type Generic2 = ({ A: A }) & { B?: never; C?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ B: [B, B, B] }) & { A?: never; C?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ C: C[] }) & { A?: never; B?: never; D?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ D: A[][][] }) & { A?: never; B?: never; C?: never; E?: never; X?: never; Y?: never; Z?: never } | ({ E: { + a: A, + b: B, + c: C, + } }) & { A?: never; B?: never; C?: never; D?: never; X?: never; Y?: never; Z?: never } | ({ X: number[] }) & { A?: never; B?: never; C?: never; D?: never; E?: never; Y?: never; Z?: never } | ({ Y: number }) & { A?: never; B?: never; C?: never; D?: never; E?: never; X?: never; Z?: never } | ({ Z: number[][] }) & { A?: never; B?: never; C?: never; D?: never; E?: never; X?: never; Y?: never }; + + export type GenericAutoBound = { + value: T, + values: T[], + }; + + export type GenericAutoBound2 = { + value: T, + values: T[], + }; + + export type GenericDefault = { + value: T, + }; + + export type GenericDefaultSkipped = { + value: T, + }; + + export type GenericDefaultSkippedNonType = { + value: number, + }; + + export type GenericFlattened = { + generic_flattened: T, + }; + + export type GenericNewType1 = T[][]; + + export type GenericParameterOrderPreserved = { + pair: Pair, + }; + + export type GenericStruct = { + arg: T, + }; + + export type GenericStruct2 = { + a: T, + b: [T, T], + c: [T, [T, T]], + d: [T, T, T], + e: [([T, T]), ([T, T]), ([T, T])], + f: T[], + g: T[][], + h: ([([T, T]), ([T, T]), ([T, T])])[], + }; + + export type GenericTuple = [T, T[], T[][]]; + + export type GenericTupleStruct = T; + + export type GenericType = "Undefined" | T; + + export type HasGenericAlias = { [key in number]: string }; + + export type InlineConstGenericContainer = { + b: { + data: [number, number], + a: [number, number], + d: [number, number, number], + }, + c: { + data: [number, number, number], + a: [number, number], + d: [number, number, number], + }, + d: [number, number], + }; + + export type InlineEnumField = { A: { + a: string, + } }; + + export type InlineFlattenGenerics = { + g: InlineFlattenGenericsG, + gi: { + t: string, + }, + } & InlineFlattenGenericsG; + + export type InlineFlattenGenericsG = { + t: T, + }; + + export type InlineOptionalType = { + optional_field: { + a: string, + } | null, + }; + + export type InlineRecursiveConstGeneric = { + data: number[], + a: number[], + d: [number, number, number], + e: InlineRecursiveConstGeneric, + }; + + export type InlineRecursiveConstGenericContainer = { + b: { + data: [number, number], + a: [number, number], + d: [number, number, number], + e: InlineRecursiveConstGeneric, + }, + c: { + data: [number, number, number], + a: [number, number], + d: [number, number, number], + e: InlineRecursiveConstGeneric, + }, + d: [number, number], + }; + + export type InlineStruct = { + ref_struct: SimpleStruct, + val: number, + }; + + export type InlineTuple = { + demo: [string, boolean], + }; + + export type InlineTuple2 = { + demo: [{ + demo: [string, boolean], + }, boolean], + }; + + export type InlinerStruct = { + inline_this: { + ref_struct: SimpleStruct, + val: number, + }, + dont_inline_this: RefStruct, + }; + + export type Inner = { + a: number, + } & FlattenedInner; + + export type InternallyTaggedD = { + type: "A", + } & { [key in string]: string }; + + export type InternallyTaggedE = { type: "A" }; + + export type InternallyTaggedF = { type: "A" }; + + export type InternallyTaggedFInner = null; + + export type InternallyTaggedH = { type: "A" }; + + export type InternallyTaggedHInner = null; + + export type InternallyTaggedL = { + type: "A", + } & { type: "A" } | { type: "B" }; + + export type InternallyTaggedLInner = { type: "A" } | { type: "B" }; + + export type InternallyTaggedM = { type: "A" }; + + export type InternallyTaggedMInner = "A" | "B"; + + export type InternallyTaggedWithAlias = InternallyTaggedWithAlias_Serialize | InternallyTaggedWithAlias_Deserialize; + + export type InternallyTaggedWithAlias_Deserialize = { + type: "A", + } & { + field: string, + } | { + bruh: string, + } | { type: "B"; other: number }; + + export type InternallyTaggedWithAlias_Serialize = ({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }; + + export type InvalidToValidType = { + cause: null, + }; + + export type Issue221External = ({ A: { + a: string, + } }) & { B?: never } | ({ B: { + b: string, + } }) & { A?: never }; + + export type Issue221UntaggedMixed = ({ a: string }) & { b?: never; values?: never } | ({ b: string }) & { a?: never; values?: never } | ({ values: { [key in string]: string } }) & { a?: never; b?: never }; + + export type Issue221UntaggedSafe = ({ a: string }) & { b?: never } | ({ b: string }) & { a?: never }; + + export type Issue281 = { + default_unity_arguments: string[], + }; + + /** https://github.com/specta-rs/specta/issues/374 */ + export type Issue374 = Issue374_Serialize | Issue374_Deserialize; + + /** https://github.com/specta-rs/specta/issues/374 */ + export type Issue374_Deserialize = { + foo?: boolean, + bar?: boolean, + }; + + /** https://github.com/specta-rs/specta/issues/374 */ + export type Issue374_Serialize = { + foo?: boolean, + bar?: boolean, + }; + + export type KebabCase = { + "test-ing": string, + }; + + export type LifetimeGenericEnum = ({ Borrowed: T }) & { Owned?: never } | ({ Owned: T }) & { Borrowed?: never }; + + export type LifetimeGenericStruct = { + borrowed: T[], + owned: T[], + }; + + export type LoadProjectEvent = { event: "started"; data: { + projectName: string, + } } | { event: "progressTest"; data: { + projectName: string, + status: string, + progress: number, + } } | { event: "finished"; data: { + projectName: string, + } }; + + export type MacroEnum = ({ Demo: string }) & { Demo2?: never } | ({ Demo2: { + demo2: string, + } }) & { Demo?: never }; + + export type MacroStruct = string; + + export type MacroStruct2 = { + demo: string, + }; + + export type MaybeValidKey = T; + + export type MyEmptyInput = Record; + + export type MyEnum = ({ A: string }) & { B?: never } | ({ B: number }) & { A?: never }; + + export type MyEnumAdjacent = { t: "Variant"; c: { + inner: First, + } }; + + export type MyEnumExternal = { Variant: { + inner: First, + } }; + + export type MyEnumTagged = { + type: "Variant", + } & First; + + export type MyEnumUntagged = { inner: First }; + + export type NamedConstGeneric = { + data: number[], + a: number[], + d: [number, number], + }; + + export type NamedConstGenericContainer = { + a: NamedConstGeneric, + b: NamedConstGeneric, + d: [number, number], + }; + + export type NestedEnum = { type: "a"; value: string } | { type: "b"; value: number }; + + export type Ninth = { t: "A"; c: string } | { t: "B" } | { t: "C"; c: { + a: string, + } } | { t: "D"; c: First }; + + export type NonOptional = string | null; + + export type Optional = Optional_Serialize | Optional_Deserialize; + + export type OptionalInEnum = ({ A?: string | null }) & { B?: never; C?: never } | ({ B: { + a: string | null, + } }) & { A?: never; C?: never } | ({ C: { + a?: string | null, + } }) & { A?: never; B?: never }; + + export type OptionalOnNamedField = string | null; + + export type OptionalOnTransparentNamedField = { + b: string | null, + }; + + export type Optional_Deserialize = { + a: number | null, + b?: number | null, + c: string | null, + d?: boolean, + }; + + export type Optional_Serialize = { + a: number | null, + b?: number | null, + c?: string, + d: boolean, + }; + + export type OverridenStruct = { + overriden_field: string, + }; + + export type Pair = { + first: Z, + second: A, + }; + + export type PlaceholderInnerField = { + a: string, + }; + + export type Recursive = { + demo: Recursive, + }; + + export type RecursiveInEnum = { A: { + demo: RecursiveInEnum, + } }; + + export type RecursiveInline = RecursiveInline; + + export type RecursiveMapValue = { + demo: { [key in string]: RecursiveMapValue }, + }; + + export type RecursiveTransparent = RecursiveInline; + + export type RefStruct = TestEnum; + + export type Regular = { [key in string]: null }; + + export type Rename = "OneWord" | "Two words"; + + export type RenameSerdeSpecialChar = { + "a/b": number, + }; + + export type RenameWithWeirdCharsField = { + "@odata.context": string, + }; + + export type RenameWithWeirdCharsVariant = { "@odata.context": string }; + + export type RenamedFieldKeys = { + "": string, + "a\"b": string, + "a\\b": string, + "line\nbreak": string, + "line\u2028break": string, + "line\u2029break": string, + }; + + export type RenamedVariantWithSkippedPayload = "a-b"; + + export type Second = { + a: number, + }; + + export type Seventh = { + a: First, + b: Second, + }; + + export type SimpleStruct = { + a: number, + b: string, + c: [number, string, number], + d: string[], + e: string | null, + }; + + /** Some single-line comment */ + export type SingleLineComment = + /** Some single-line comment */ + ({ A: number }) & { B?: never } | + /** Some single-line comment */ + ({ B: { + /** Some single-line comment */ + a: number, + } }) & { A?: never }; + + export type Sixth = { + a: First, + b: First, + }; + + export type SkipField = { + b: number, + }; + + export type SkipNamedFieldInVariant = ({ A: Record }) & { B?: never } | ({ B: { + b: number, + } }) & { A?: never }; + + export type SkipOnlyField = Record; + + export type SkipStructFields = { + a: number, + }; + + export type SkipUnnamedFieldInVariant = "A" | { B: [number] }; + + export type SkipVariant = { A: string }; + + export type SkipVariant2 = { tag: "A"; data: string }; + + export type SkipVariant3 = { A: { + a: string, + } }; + + export type SkippedFieldWithinVariant = { type: "A" } | { type: "B"; data: string }; + + export type SpectaSkipNonTypeField = { + a: number, + }; + + export type SpectaTypeOverride = { + string_ident: string, + u32_ident: number, + path: string, + tuple: [string, number], + }; + + export type Struct2 = { + b: string, + }; + + export type StructNew = { + t: "StructNew", + a: string, + }; + + export type StructPhaseSpecificRename = StructPhaseSpecificRenameSerialize | StructPhaseSpecificRenameDeserialize; + + export type StructPhaseSpecificRenameDeserialize = { + kind: "StructPhaseSpecificRenameDeserialize", + der: string, + }; + + export type StructPhaseSpecificRenameSerialize = { + kind: "StructPhaseSpecificRenameSerialize", + ser: string, + }; + + export type StructRenameAllUppercase = { + A: number, + B: number, + }; + + export type StructWithAlias = StructWithAlias_Serialize | StructWithAlias_Deserialize; + + export type StructWithAliasAndRename = StructWithAliasAndRename_Serialize | StructWithAliasAndRename_Deserialize; + + export type StructWithAliasAndRename_Deserialize = { + renamed_field: string, + }; + + export type StructWithAliasAndRename_Serialize = { + renamed_field: string, + }; + + export type StructWithAlias_Deserialize = { + field: string, + } | { + bruh: string, + }; + + export type StructWithAlias_Serialize = { + field: string, + }; + + export type StructWithMultipleAliases = StructWithMultipleAliases_Serialize | StructWithMultipleAliases_Deserialize; + + export type StructWithMultipleAliases_Deserialize = { + field: string, + } | { + bruh: string, + } | { + alternative: string, + } | { + another: string, + }; + + export type StructWithMultipleAliases_Serialize = { + field: string, + }; + + export type TagOnStructWithInline = { + type: "TagOnStructWithInline", + a: First, + b: { + a: string, + }, + }; + + export type Tenth = string | "B" | { + a: string, + } | First; + + export type TestCollectionRegister = never; + + export type TestEnum = "Unit" | ({ Single: number }) & { Multiple?: never; Struct?: never } | ({ Multiple: [number, number] }) & { Single?: never; Struct?: never } | ({ Struct: { + a: number, + } }) & { Multiple?: never; Single?: never }; + + export type Third = { + b: { [key in string]: string }, + c: First, + } & First; + + export type ToBeFlattened = { + a: string, + }; + + export type TransparentStruct = string; + + export type TransparentType = TransparentTypeInner; + + export type TransparentType2 = null; + + export type TransparentTypeInner = { + inner: string, + }; + + export type TransparentTypeWithOverride = string; + + export type TransparentWithSkip = null; + + export type TransparentWithSkip2 = string; + + export type TransparentWithSkip3 = string; + + export type TupleNested = [number[], [number[], number[]], [number[], number[], number[]]]; + + export type TupleStruct = string; + + export type TupleStruct1 = number; + + export type TupleStruct3 = [number, boolean, string]; + + export type TupleStructWithRep = string; + + export type Unit1 = null; + + export type Unit2 = Record; + + export type Unit3 = []; + + export type Unit4 = null; + + export type Unit5 = "A"; + + export type Unit6 = { A: null }; + + export type Unit7 = { A: Record }; + + export type UnitVariants = "A" | "B" | "C"; + + export type UntaggedVariants = string | number | { id: string } | [string, boolean]; + + export type UntaggedVariantsKey = string | number; + + export type UntaggedVariantsWithDuplicateBranches = null | number; + + export type UntaggedVariantsWithoutValue = string | [number, string] | number; + + export type UntaggedWithAlias = UntaggedWithAlias_Serialize | UntaggedWithAlias_Deserialize; + + export type UntaggedWithAlias_Deserialize = { + field: string, + } | { + bruh: string, + } | { other: number }; + + export type UntaggedWithAlias_Serialize = ({ field: string }) & { other?: never } | ({ other: number }) & { field?: never }; + + export type ValidMaybeValidKey = { [key in MaybeValidKey]: null }; + + export type ValidMaybeValidKeyNested = { [key in MaybeValidKey>]: null }; + ════════════════════════════════════════ + +tests/ + tests/ + types.ts (12382 bytes) + ──────────────────────────────────────── + // This file has been generated by Specta. Do not edit this file manually. + + import type * as std$ops from "../../std/ops"; + import type * as std$result from "../../std/result"; + import type * as test$types from "../../test/types"; + import type * as test$types$type_type from "../../test/types/type_type"; + export type Primitives = { + i8: number, + i16: number, + i32: number, + u8: number, + u16: number, + u32: number, + f32: number | null, + f64: number | null, + bool: boolean, + char: string, + "Range": std$ops.Range, + "RangeInclusive": std$ops.RangeInclusive, + "()": null, + "(String, i32)": [string, number], + "(String, i32, bool)": [string, number, boolean], + "((String, i32), (bool, char, bool), ())": [[string, number], [boolean, string, boolean], null], + "(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)": [boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean], + "(Vec, Vec)": [number[], boolean[]], + String: string, + PathBuf: string, + IpAddr: string, + Ipv4Addr: string, + Ipv6Addr: string, + SocketAddr: string, + SocketAddrV4: string, + SocketAddrV6: string, + "Cow<'static, str>": string, + "Cow<'static, i32>": number, + "&'static str": string, + "&'static bool": boolean, + "&'static i32": number, + "Vec": number[], + "&'static [i32]": number[], + "&'static [i32; 3]": [number, number, number], + "[i32; 3]": [number, number, number], + "Vec": test$types.MyEnum[], + "&'static [MyEnum]": test$types.MyEnum[], + "&'static [MyEnum; 6]": [test$types.MyEnum, test$types.MyEnum, test$types.MyEnum, test$types.MyEnum, test$types.MyEnum, test$types.MyEnum], + "[MyEnum; 2]": [test$types.MyEnum, test$types.MyEnum], + "&'static [i32; 1]": [number], + "&'static [i32; 0]": [], + "Option": number | null, + "Option<()>": null, + "Option>": number[] | null, + "Result": std$result.Result, + "Vec>>": (number | null)[], + "Option>>": number[] | null, + "[Vec; 3]": [string[], string[], string[]], + "Option>": string | null, + "Option>>": string | null, + "PhantomData<()>": null, + "PhantomData": null, + Infallible: never, + Unit1: test$types.Unit1, + Unit2: test$types.Unit2, + Unit3: test$types.Unit3, + Unit4: test$types.Unit4, + Unit5: test$types.Unit5, + Unit6: test$types.Unit6, + Unit7: test$types.Unit7, + SimpleStruct: test$types.SimpleStruct, + TupleStruct1: test$types.TupleStruct1, + TupleStruct3: test$types.TupleStruct3, + TestEnum: test$types.TestEnum, + RefStruct: test$types.RefStruct, + InlinerStruct: test$types.InlinerStruct, + "GenericStruct": test$types.GenericStruct, + "GenericStruct": test$types.GenericStruct, + FlattenEnumStruct: test$types.FlattenEnumStruct, + OverridenStruct: test$types.OverridenStruct, + HasGenericAlias: test$types.HasGenericAlias, + EnumMacroAttributes: test$types.EnumMacroAttributes, + InlineEnumField: test$types.InlineEnumField, + InlineOptionalType: test$types.InlineOptionalType, + Rename: test$types.Rename, + TransparentType: test$types.TransparentType, + TransparentType2: test$types.TransparentType2, + TransparentTypeWithOverride: test$types.TransparentTypeWithOverride, + "[Option; 3]": [(number | null), (number | null), (number | null)], + "HashMap": Partial<{ [key in test$types.BasicEnum]: null }>, + "HashMap": Partial<{ [key in test$types.BasicEnum]: number }>, + "Option>>>": number | null, + "Vec": test$types.PlaceholderInnerField[], + EnumReferenceRecordKey: test$types.EnumReferenceRecordKey, + FlattenOnNestedEnum: test$types.FlattenOnNestedEnum, + MyEmptyInput: test$types.MyEmptyInput, + "(String)": string, + "(String,)": [string], + ExtraBracketsInTupleVariant: test$types.ExtraBracketsInTupleVariant, + ExtraBracketsInUnnamedStruct: test$types.ExtraBracketsInUnnamedStruct, + "Vec": test$types.MyEnum[], + InlineTuple: test$types.InlineTuple, + InlineTuple2: test$types.InlineTuple2, + "Box": string, + "Box": string, + SkippedFieldWithinVariant: test$types.SkippedFieldWithinVariant, + KebabCase: test$types.KebabCase, + "&[&str]": string[], + "Issue281<'_>": test$types.Issue281, + "LifetimeGenericStruct<'_, i32>": test$types.LifetimeGenericStruct, + "LifetimeGenericEnum<'_, i32>": test$types.LifetimeGenericEnum, + RenameWithWeirdCharsField: test$types.RenameWithWeirdCharsField, + RenameWithWeirdCharsVariant: test$types.RenameWithWeirdCharsVariant, + RenamedFieldKeys: test$types.RenamedFieldKeys, + RenamedVariantWithSkippedPayload: test$types.RenamedVariantWithSkippedPayload, + "type_type::Type": test$types$type_type.Type, + ActualType: test$types.ActualType, + SpectaTypeOverride: test$types.SpectaTypeOverride, + ContainerTypeOverrideStruct: test$types.ContainerTypeOverrideStruct, + ContainerTypeOverrideEnum: test$types.ContainerTypeOverrideEnum, + "ContainerTypeOverrideGeneric>": test$types.ContainerTypeOverrideGeneric, + "ContainerTypeOverrideToGeneric": test$types.ContainerTypeOverrideToGeneric, + ContainerTypeOverrideTuple: test$types.ContainerTypeOverrideTuple, + "ContainerTypeOverrideTupleGeneric": test$types.ContainerTypeOverrideTupleGeneric, + InvalidToValidType: test$types.InvalidToValidType, + TupleStruct: test$types.TupleStruct, + TupleStructWithRep: test$types.TupleStructWithRep, + "GenericTupleStruct": test$types.GenericTupleStruct, + BracedStruct: test$types.BracedStruct, + Struct: test$types.StructNew, + Struct2: test$types.Struct2, + Enum: test$types.Enum, + Enum2: test$types.Enum2, + Enum3: test$types.Enum3, + StructRenameAllUppercase: test$types.StructRenameAllUppercase, + RenameSerdeSpecialChar: test$types.RenameSerdeSpecialChar, + EnumRenameAllUppercase: test$types.EnumRenameAllUppercase, + Recursive: test$types.Recursive, + RecursiveMapValue: test$types.RecursiveMapValue, + RecursiveTransparent: test$types.RecursiveTransparent, + RecursiveInEnum: test$types.RecursiveInEnum, + NonOptional: test$types.NonOptional, + OptionalOnNamedField: test$types.OptionalOnNamedField, + OptionalOnTransparentNamedField: test$types.OptionalOnTransparentNamedField, + OptionalInEnum: test$types.OptionalInEnum, + UntaggedVariants: test$types.UntaggedVariants, + UntaggedVariantsWithoutValue: test$types.UntaggedVariantsWithoutValue, + UntaggedVariantsWithDuplicateBranches: test$types.UntaggedVariantsWithDuplicateBranches, + "HashMap": { [key in string]: null }, + Regular: test$types.Regular, + "HashMap": { [key in never]: null }, + "HashMap": { [key in test$types.TransparentStruct]: null }, + "HashMap": Partial<{ [key in test$types.UnitVariants]: null }>, + "HashMap": Partial<{ [key in test$types.UntaggedVariantsKey]: null }>, + ValidMaybeValidKey: test$types.ValidMaybeValidKey, + ValidMaybeValidKeyNested: test$types.ValidMaybeValidKeyNested, + MacroStruct: test$types.MacroStruct, + MacroStruct2: test$types.MacroStruct2, + MacroEnum: test$types.MacroEnum, + DeprecatedType: test$types.DeprecatedType, + DeprecatedTypeWithMsg: test$types.DeprecatedTypeWithMsg, + DeprecatedTypeWithMsg2: test$types.DeprecatedTypeWithMsg2, + DeprecatedFields: test$types.DeprecatedFields, + DeprecatedTupleVariant: test$types.DeprecatedTupleVariant, + DeprecatedEnumVariants: test$types.DeprecatedEnumVariants, + CommentedStruct: test$types.CommentedStruct, + CommentedEnum: test$types.CommentedEnum, + SingleLineComment: test$types.SingleLineComment, + NonGeneric: test$types.Demo, + "HalfGenericA": test$types.Demo, + "HalfGenericB": test$types.Demo, + "FullGeneric": test$types.Demo, + "Another": test$types.Demo, + "MapA": { [key in string]: number }, + "MapB": { [key in number]: string }, + "MapC": { [key in string]: test$types.AGenericStruct }, + "AGenericStruct": test$types.AGenericStruct, + A: test$types.A, + DoubleFlattened: test$types.DoubleFlattened, + FlattenedInner: test$types.FlattenedInner, + BoxFlattened: test$types.BoxFlattened, + BoxInline: test$types.BoxInline, + First: test$types.First, + Second: test$types.Second, + Third: test$types.Third, + Fourth: test$types.Fourth, + TagOnStructWithInline: test$types.TagOnStructWithInline, + Sixth: test$types.Sixth, + Seventh: test$types.Seventh, + Eight: test$types.Eight, + Ninth: test$types.Ninth, + Tenth: test$types.Tenth, + MyEnumTagged: test$types.MyEnumTagged, + MyEnumExternal: test$types.MyEnumExternal, + MyEnumAdjacent: test$types.MyEnumAdjacent, + MyEnumUntagged: test$types.MyEnumUntagged, + EmptyStruct: test$types.EmptyStruct, + EmptyStructWithTag: test$types.EmptyStructWithTag, + AdjacentlyTagged: test$types.AdjacentlyTagged, + LoadProjectEvent: test$types.LoadProjectEvent, + ExternallyTagged: test$types.ExternallyTagged, + Issue221External: test$types.Issue221External, + InternallyTaggedD: test$types.InternallyTaggedD, + InternallyTaggedE: test$types.InternallyTaggedE, + InternallyTaggedF: test$types.InternallyTaggedF, + InternallyTaggedH: test$types.InternallyTaggedH, + InternallyTaggedL: test$types.InternallyTaggedL, + InternallyTaggedM: test$types.InternallyTaggedM, + Issue221UntaggedSafe: test$types.Issue221UntaggedSafe, + Issue221UntaggedMixed: test$types.Issue221UntaggedMixed, + EmptyEnum: test$types.EmptyEnum, + EmptyEnumTagged: test$types.EmptyEnumTagged, + EmptyEnumTaggedWContent: test$types.EmptyEnumTaggedWContent, + EmptyEnumUntagged: test$types.EmptyEnumUntagged, + SkipOnlyField: test$types.SkipOnlyField, + SkipField: test$types.SkipField, + SkipVariant: test$types.SkipVariant, + SkipUnnamedFieldInVariant: test$types.SkipUnnamedFieldInVariant, + SkipNamedFieldInVariant: test$types.SkipNamedFieldInVariant, + TransparentWithSkip: test$types.TransparentWithSkip, + TransparentWithSkip2: test$types.TransparentWithSkip2, + TransparentWithSkip3: test$types.TransparentWithSkip3, + SkipVariant2: test$types.SkipVariant2, + SkipVariant3: test$types.SkipVariant3, + SkipStructFields: test$types.SkipStructFields, + SpectaSkipNonTypeField: test$types.SpectaSkipNonTypeField, + FlattenA: test$types.FlattenA, + FlattenB: test$types.FlattenB, + FlattenC: test$types.FlattenC, + FlattenD: test$types.FlattenD, + FlattenE: test$types.FlattenE, + FlattenF: test$types.FlattenF, + FlattenG: test$types.FlattenG, + TupleNested: test$types.TupleNested, + "Generic1<()>": test$types.Generic1, + "GenericAutoBound<()>": test$types.GenericAutoBound, + "GenericAutoBound2<()>": test$types.GenericAutoBound2, + Container1: test$types.Container1, + "Generic2<(), String, i32>": test$types.Generic2, + "GenericNewType1<()>": test$types.GenericNewType1, + "GenericTuple<()>": test$types.GenericTuple, + "GenericStruct2<()>": test$types.GenericStruct2, + "InlineGenericNewtype": string, + "InlineGenericNested": [string, string[], [string, string], { [key in string]: string }, string | null, "Unit" | ({ Unnamed: string }) & { Named?: never } | ({ Named: { + value: string, + } }) & { Unnamed?: never }], + "InlineFlattenGenericsG<()>": test$types.InlineFlattenGenericsG, + InlineFlattenGenerics: test$types.InlineFlattenGenerics, + GenericDefault: test$types.GenericDefault, + ChainedGenericDefault: test$types.ChainedGenericDefault, + "ChainedGenericDefault": test$types.ChainedGenericDefault, + "ChainedGenericDefault": test$types.ChainedGenericDefault, + "ChainedGenericDefault": test$types.ChainedGenericDefault, + GenericDefaultSkipped: test$types.GenericDefaultSkipped, + GenericDefaultSkippedNonType: test$types.GenericDefaultSkippedNonType, + GenericParameterOrderPreserved: test$types.GenericParameterOrderPreserved, + ConstGenericInNonConstContainer: test$types.ConstGenericInNonConstContainer, + ConstGenericInConstContainer: test$types.ConstGenericInConstContainer, + NamedConstGenericContainer: test$types.NamedConstGenericContainer, + InlineConstGenericContainer: test$types.InlineConstGenericContainer, + InlineRecursiveConstGenericContainer: test$types.InlineRecursiveConstGenericContainer, + TestCollectionRegister: test$types.TestCollectionRegister, + TestCollectionRegister: test$types.TestCollectionRegister, + }; + ════════════════════════════════════════ diff --git a/tests/tests/snapshots/test__typescript__ts-export-to-flatfile-serde.snap b/tests/tests/snapshots/test__typescript__ts-export-to-flatfile-serde.snap index 12e2fe4a..ab3c2606 100644 --- a/tests/tests/snapshots/test__typescript__ts-export-to-flatfile-serde.snap +++ b/tests/tests/snapshots/test__typescript__ts-export-to-flatfile-serde.snap @@ -1,8 +1,9 @@ --- source: tests/tests/typescript.rs +assertion_line: 946 expression: output --- -ts-export-to-flatfile-serde (25724 bytes) +ts-export-to-flatfile-serde (25720 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. export type A = { @@ -540,7 +541,9 @@ export type MyEnumExternal = { Variant: { inner: First, } }; -export type MyEnumTagged = { type: "Variant"; inner: First }; +export type MyEnumTagged = { + type: "Variant", +} & First; export type MyEnumUntagged = { inner: First }; diff --git a/tests/tests/snapshots/test__typescript__ts-export-to-flatfile-serde_phases.snap b/tests/tests/snapshots/test__typescript__ts-export-to-flatfile-serde_phases.snap index c18a8515..9121f76f 100644 --- a/tests/tests/snapshots/test__typescript__ts-export-to-flatfile-serde_phases.snap +++ b/tests/tests/snapshots/test__typescript__ts-export-to-flatfile-serde_phases.snap @@ -2,7 +2,7 @@ source: tests/tests/typescript.rs expression: output --- -ts-export-to-flatfile-serde_phases (29668 bytes) +ts-export-to-flatfile-serde_phases (29604 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. export type A = { @@ -513,16 +513,13 @@ export type InternallyTaggedMInner = "A" | "B"; export type InternallyTaggedWithAlias = InternallyTaggedWithAlias_Serialize | InternallyTaggedWithAlias_Deserialize; -export type InternallyTaggedWithAlias_Deserialize = ({ A: { +export type InternallyTaggedWithAlias_Deserialize = { type: "A", } & { field: string, } | { bruh: string, -} }) & { B?: never } | ({ B: { - type: "B", - other: number, -} }) & { A?: never }; +} | { type: "B"; other: number }; export type InternallyTaggedWithAlias_Serialize = ({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }; @@ -604,7 +601,9 @@ export type MyEnumExternal = { Variant: { inner: First, } }; -export type MyEnumTagged = { type: "Variant"; inner: First }; +export type MyEnumTagged = { + type: "Variant", +} & First; export type MyEnumUntagged = { inner: First }; @@ -652,7 +651,7 @@ export type Optional_Deserialize = { export type Optional_Serialize = { a: number | null, b?: number | null, - c?: string | null, + c?: string, d: boolean, }; diff --git a/tests/tests/snapshots/test__typescript__ts-export-to-moduleprefixedname-serde.snap b/tests/tests/snapshots/test__typescript__ts-export-to-moduleprefixedname-serde.snap index d1ae649f..24ec8b58 100644 --- a/tests/tests/snapshots/test__typescript__ts-export-to-moduleprefixedname-serde.snap +++ b/tests/tests/snapshots/test__typescript__ts-export-to-moduleprefixedname-serde.snap @@ -1,8 +1,9 @@ --- source: tests/tests/typescript.rs +assertion_line: 946 expression: output --- -ts-export-to-moduleprefixedname-serde (30711 bytes) +ts-export-to-moduleprefixedname-serde (30707 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. export type test_types_A = { @@ -540,7 +541,9 @@ export type test_types_MyEnumExternal = { Variant: { inner: test_types_First, } }; -export type test_types_MyEnumTagged = { type: "Variant"; inner: test_types_First }; +export type test_types_MyEnumTagged = { + type: "Variant", +} & test_types_First; export type test_types_MyEnumUntagged = { inner: test_types_First }; diff --git a/tests/tests/snapshots/test__typescript__ts-export-to-moduleprefixedname-serde_phases.snap b/tests/tests/snapshots/test__typescript__ts-export-to-moduleprefixedname-serde_phases.snap index 9fe1f170..fbdcac26 100644 --- a/tests/tests/snapshots/test__typescript__ts-export-to-moduleprefixedname-serde_phases.snap +++ b/tests/tests/snapshots/test__typescript__ts-export-to-moduleprefixedname-serde_phases.snap @@ -2,7 +2,7 @@ source: tests/tests/typescript.rs expression: output --- -ts-export-to-moduleprefixedname-serde_phases (35315 bytes) +ts-export-to-moduleprefixedname-serde_phases (35251 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. export type test_types_A = { @@ -513,16 +513,13 @@ export type test_types_InternallyTaggedMInner = "A" | "B"; export type test_types_InternallyTaggedWithAlias = test_types_InternallyTaggedWithAlias_Serialize | test_types_InternallyTaggedWithAlias_Deserialize; -export type test_types_InternallyTaggedWithAlias_Deserialize = ({ A: { +export type test_types_InternallyTaggedWithAlias_Deserialize = { type: "A", } & { field: string, } | { bruh: string, -} }) & { B?: never } | ({ B: { - type: "B", - other: number, -} }) & { A?: never }; +} | { type: "B"; other: number }; export type test_types_InternallyTaggedWithAlias_Serialize = ({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }; @@ -604,7 +601,9 @@ export type test_types_MyEnumExternal = { Variant: { inner: test_types_First, } }; -export type test_types_MyEnumTagged = { type: "Variant"; inner: test_types_First }; +export type test_types_MyEnumTagged = { + type: "Variant", +} & test_types_First; export type test_types_MyEnumUntagged = { inner: test_types_First }; @@ -652,7 +651,7 @@ export type test_types_Optional_Deserialize = { export type test_types_Optional_Serialize = { a: number | null, b?: number | null, - c?: string | null, + c?: string, d: boolean, }; diff --git a/tests/tests/snapshots/test__typescript__ts-export-to-namespaces-serde.snap b/tests/tests/snapshots/test__typescript__ts-export-to-namespaces-serde.snap index 57b68207..807de9d3 100644 --- a/tests/tests/snapshots/test__typescript__ts-export-to-namespaces-serde.snap +++ b/tests/tests/snapshots/test__typescript__ts-export-to-namespaces-serde.snap @@ -1,8 +1,9 @@ --- source: tests/tests/typescript.rs +assertion_line: 946 expression: output --- -ts-export-to-namespaces-serde (32556 bytes) +ts-export-to-namespaces-serde (32552 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. @@ -568,7 +569,9 @@ number]; inner: $s$.test.types.First, } }; - export type MyEnumTagged = { type: "Variant"; inner: $s$.test.types.First }; + export type MyEnumTagged = { + type: "Variant", +} & $s$.test.types.First; export type MyEnumUntagged = { inner: $s$.test.types.First }; diff --git a/tests/tests/snapshots/test__typescript__ts-export-to-namespaces-serde_phases.snap b/tests/tests/snapshots/test__typescript__ts-export-to-namespaces-serde_phases.snap index 7b4e4198..13671fab 100644 --- a/tests/tests/snapshots/test__typescript__ts-export-to-namespaces-serde_phases.snap +++ b/tests/tests/snapshots/test__typescript__ts-export-to-namespaces-serde_phases.snap @@ -2,7 +2,7 @@ source: tests/tests/typescript.rs expression: output --- -ts-export-to-namespaces-serde_phases (37061 bytes) +ts-export-to-namespaces-serde_phases (36997 bytes) ──────────────────────────────────────── // This file has been generated by Specta. Do not edit this file manually. @@ -541,16 +541,13 @@ number]; export type InternallyTaggedWithAlias = $s$.test.types.InternallyTaggedWithAlias_Serialize | $s$.test.types.InternallyTaggedWithAlias_Deserialize; - export type InternallyTaggedWithAlias_Deserialize = ({ A: { + export type InternallyTaggedWithAlias_Deserialize = { type: "A", } & { field: string, } | { bruh: string, -} }) & { B?: never } | ({ B: { - type: "B", - other: number, -} }) & { A?: never }; +} | { type: "B"; other: number }; export type InternallyTaggedWithAlias_Serialize = ({ type: "A"; field: string }) & { other?: never } | ({ type: "B"; other: number }) & { field?: never }; @@ -632,7 +629,9 @@ number]; inner: $s$.test.types.First, } }; - export type MyEnumTagged = { type: "Variant"; inner: $s$.test.types.First }; + export type MyEnumTagged = { + type: "Variant", +} & $s$.test.types.First; export type MyEnumUntagged = { inner: $s$.test.types.First }; @@ -680,7 +679,7 @@ number]; export type Optional_Serialize = { a: number | null, b?: number | null, - c?: string | null, + c?: string, d: boolean, }; diff --git a/tests/tests/typescript.rs b/tests/tests/typescript.rs index 36e18a9c..061bce28 100644 --- a/tests/tests/typescript.rs +++ b/tests/tests/typescript.rs @@ -1192,3 +1192,58 @@ fn reserved_names() { // // Tests for framework primitives (prelude, runtime, runtime imports, etc) // Tauri `Channel` tests + +#[test] +fn internally_tagged_enum_with_content_variants_renders_correctly() { + #[derive(Type, serde::Serialize)] + #[specta(collect = false)] + struct ItcInner { + field: String, + } + + #[derive(Type, serde::Serialize)] + #[specta(collect = false)] + #[serde(tag = "type")] + enum InternallyTaggedWithContent { + A { + #[serde(flatten)] + inner: ItcInner, + }, + B { + #[serde(flatten)] + inner: ItcInner, + }, + #[serde(other)] + Unknown, + } + + let mut types = Types::default(); + let _ = ::definition(&mut types); + let _ = ::definition(&mut types); + + let output = Typescript::default() + .export(&types, &specta_serde::PhasesFormat) + .unwrap(); + + // Wire format produced by serde at runtime is `{ "type": "A", ...flattened_inner }` + // (internally-tagged: tag at top level alongside the variant payload). + // The TS bindings must describe that shape -- not the externally-tagged + // `{ "A": payload } & { "B"?: never; ... }` shape that rc.25 regressed to + // when the enum had a `#[serde(other)]` variant. + assert!( + !output.contains("A?: never") && !output.contains("B?: never"), + "rc.25 regression: variants wrapped in externally-tagged shape with `?: never` exclusions. Output:\n{output}" + ); + assert!( + output.contains(r#"type: "A""#) && output.contains(r#"type: "B""#), + "expected `type: \"A\"` and `type: \"B\"` literals as tag discriminators. Output:\n{output}" + ); + // The `inner` field is `#[serde(flatten)]`, so on the wire the inner + // struct's fields appear at the top level of the variant -- the TS + // shape must be `({ type: "A" } & ItcInner)`, never + // `{ type: "A"; inner: ItcInner }`. + assert!( + !output.contains("inner:"), + "rc.25 regression: `#[serde(flatten)]` ignored on struct-variant fields in internally-tagged enums; the inner type is being kept under an `inner:` key instead of merged. Output:\n{output}" + ); +}