Skip to content

Commit fb6c1f0

Browse files
Keep order of generic args (fixes #400)
This is a breaking change to public interface (Reference::generics, Reference::generics_mut), but I think it's justified (returning HashMap there was misleading).
1 parent 334b006 commit fb6c1f0

File tree

4 files changed

+32
-11
lines changed

4 files changed

+32
-11
lines changed

specta-serde/src/validate.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ fn inner(
9999
checked_references.insert(r.sid());
100100
// TODO: We don't error here for `Any`/`Unknown` in the TS exporter
101101
if let Some(ty) = types.get(r.sid()) {
102-
inner(ty.ty(), types, r.generics(), checked_references)?;
102+
let generics_map: BTreeMap<_, _> = r.generics().iter().cloned().collect();
103+
inner(ty.ty(), types, &generics_map, checked_references)?;
103104
}
104105
}
105106
}
@@ -177,8 +178,8 @@ fn is_valid_map_key(
177178
}
178179
DataType::Reference(r) => {
179180
let ty = types.get(r.sid()).expect("Type was never populated"); // TODO: Error properly
180-
181-
is_valid_map_key(ty.ty(), types, r.generics())
181+
let generics_map: BTreeMap<_, _> = r.generics().iter().cloned().collect();
182+
is_valid_map_key(ty.ty(), types, &generics_map)
182183
}
183184
DataType::Generic(g) => {
184185
let ty = generics.get(g).expect("bruh");

specta-typescript/src/inline.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ fn inner(
150150
false,
151151
truely_force_inline,
152152
&r.generics()
153-
.clone()
154-
.into_iter()
153+
.iter()
154+
.cloned()
155155
.map(|(g, mut dt)| {
156156
resolve_generics(&mut dt, generics);
157157
(g, dt)

specta/src/datatype/reference.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
//! Helpers for generating [Type::reference] implementations.
22
3-
use std::collections::BTreeMap;
4-
53
use crate::SpectaID;
64

75
use super::{DataType, Generic};
@@ -11,15 +9,15 @@ use super::{DataType, Generic};
119
#[non_exhaustive]
1210
pub struct Reference {
1311
pub(crate) sid: SpectaID,
14-
pub(crate) generics: BTreeMap<Generic, DataType>,
12+
pub(crate) generics: Vec<(Generic, DataType)>,
1513
pub(crate) inline: bool,
1614
}
1715

1816
impl Reference {
1917
/// TODO: Explain invariant.
2018
pub fn construct(
2119
sid: SpectaID,
22-
generics: impl Into<BTreeMap<Generic, DataType>>,
20+
generics: impl Into<Vec<(Generic, DataType)>>,
2321
inline: bool,
2422
) -> Self {
2523
Self {
@@ -35,12 +33,12 @@ impl Reference {
3533
}
3634

3735
/// Get the generic parameters set on this reference which will be filled in by the [NamedDataType].
38-
pub fn generics(&self) -> &BTreeMap<Generic, DataType> {
36+
pub fn generics(&self) -> &[(Generic, DataType)] {
3937
&self.generics
4038
}
4139

4240
/// Get the generic parameters set on this reference which will be filled in by the [NamedDataType].
43-
pub fn generics_mut(&mut self) -> &mut BTreeMap<Generic, DataType> {
41+
pub fn generics_mut(&mut self) -> &mut Vec<(Generic, DataType)> {
4442
&mut self.generics
4543
}
4644

tests/tests/ts_rs/generics.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,25 @@ fn inline() {
219219

220220
// assert_ts_export!(D::<&str, 41>, "export type D<T> = { t: Array<T>, }")
221221
// }
222+
223+
// https://github.com/specta-rs/specta/issues/400
224+
#[test]
225+
fn generic_parameter_order_preserved() {
226+
#[derive(Type)]
227+
#[specta(export = false)]
228+
struct Pair<Z, A> {
229+
first: Z,
230+
second: A,
231+
}
232+
233+
#[derive(Type)]
234+
#[specta(export = false)]
235+
struct Container {
236+
pair: Pair<i32, String>,
237+
}
238+
239+
assert_ts_export!(
240+
Container,
241+
"export type Container = { pair: Pair<number, string> };"
242+
);
243+
}

0 commit comments

Comments
 (0)