Coming from TypeScript background, it is common to use either a union type or a generic hints on function parameters.
For rust though, at some point, you need to specify the type.
I have these structs (oversimplified):
#[derive(Serialize, Deserialize)]
struct PublishedJob {
id: String,
job: String,
data: String,
}
#[derive(Serialize, Deserialize)]
struct PublishedEvent {
id: String,
event: String,
data: String,
}
I have a function that should accept either a job or an event. In TypeScript, it may look like this:
// When using generics
function publish(message: T) {
// do stuff
}
// When using union types
function publish(message: PublishedJob | PublishedEvent) {
// do stuff
}
I wanted to have the same structure as rust. Using generics don't work since I need to specify the type at some point but the type depends on some runtime data.
Then I realized I could just use enums instead.
#[derive(Serialize, Deserialize)]
enum PublishedPayload {
Job(PublishedJob),
Event(PublishedEvent),
}
Then my function signature will look like this:
fn publish(message: PublishedPayload) {
// do stuff
}
It works and all, however, serde wrapped the object with Job
or Event
property when serialized. I just want the internal object.
To fix this, we tell serde to use internal tag.
https://serde.rs/enum-representations.html
#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
enum PublishedPayload {
Job(PublishedJob),
Event(PublishedEvent),
}