Skip to content

Commit

Permalink
fix bugs in internally tagged tests
Browse files Browse the repository at this point in the history
  • Loading branch information
oscartbeaumont committed Sep 4, 2023
1 parent 1de66b9 commit a33fe77
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
15 changes: 13 additions & 2 deletions src/lang/ts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,13 +411,24 @@ fn enum_datatype(ctx: ExportContext, e: &EnumType, type_map: &TypeMap) -> Output
format!("{{ {tag}: {sanitised_name} }}")
}
(EnumRepr::Internal { tag }, EnumVariant::Unnamed(tuple)) => {
let typ = unnamed_fields_datatype(
let mut typ = unnamed_fields_datatype(
ctx.clone(),
&tuple.fields,
type_map,
"[]",
)?;
format!("({{ {tag}: {sanitised_name} }} & {typ})")

// TODO: This `null` check is a bad fix for an internally tagged type with a `null` variant being exported as `{ type: "A" } & null` (which is `never` in TS)
// TODO: Move this check into the macros so it can apply to any language cause it should (it's just hard to do in the macros)
if typ == "null" {
format!("({{ {tag}: {sanitised_name} }})")
} else {
// We wanna be sure `... & ... | ...` becomes `... & (... | ...)`
if typ.contains("|") {

Check warning on line 427 in src/lang/ts/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

single-character string constant used as pattern

warning: single-character string constant used as pattern --> src/lang/ts/mod.rs:427:49 | 427 | ... if typ.contains("|") { | ^^^ help: try using a `char` instead: `'|'` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern = note: `#[warn(clippy::single_char_pattern)]` implied by `#[warn(clippy::all)]`
typ = format!("({typ})");
}
format!("({{ {tag}: {sanitised_name} }} & {typ})")
}
}
(EnumRepr::Internal { tag }, EnumVariant::Named(obj)) => {
let mut fields = vec![format!("{tag}: {sanitised_name}")];
Expand Down
12 changes: 7 additions & 5 deletions tests/serde/internally_tagged.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ pub struct IInner(String);
#[serde(export = false, tag = "type")]
pub enum L {
// Internally tag enum with inlined field that is itself internally tagged
A(#[specta(inline)] LInner),
#[specta(inline)]
A(LInner),
}

#[derive(Type)]
Expand All @@ -107,7 +108,8 @@ pub enum LInner {
pub enum M {
// Internally tag enum with inlined field that is untagged
// `MInner` is `null` - Test `B` in `untagged.rs`
A(#[specta(inline)] MInner),
#[specta(inline)]
A(MInner),
}

#[derive(Type)]
Expand All @@ -123,11 +125,11 @@ fn internally_tagged() {
assert_ts!(error; B, SerdeError::InvalidInternallyTaggedEnum);
assert_ts!(error; C, SerdeError::InvalidInternallyTaggedEnum);
assert_ts!(D, "({ type: \"A\" } & { [key in string]: string })");
assert_ts!(E, "{ type: \"A\" }"); // TODO: Specta adding `& null` becomes `never` in TS. Serde ignores it.
assert_ts!(E, "({ type: \"A\" })");
assert_ts!(F, "({ type: \"A\" } & FInner)");
assert_ts!(error; G, SerdeError::InvalidInternallyTaggedEnum);
assert_ts!(H, "({ type: \"A\" } & HInner)");
assert_ts!(error; I, SerdeError::InvalidInternallyTaggedEnum);
assert_ts!(L, "{ type: \"A\" } & ({ type: \"A\" } | { type: \"B\" })"); // TODO: Is not inlining correctly
assert_ts!(M, "{ type: \"A\" }"); // `MInner` resolves to `null`. `null & { ... }` should become `{ ... }` as that's Serde's behaviour. // TODO: Is not inlining correctly
assert_ts!(L, "({ type: \"A\" } & ({ type: \"A\" } | { type: \"B\" }))");
assert_ts!(M, "({ type: \"A\" })");
}

0 comments on commit a33fe77

Please sign in to comment.