Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to generate numeric enums? #140

Open
ottosson opened this issue Feb 6, 2023 · 9 comments
Open

Is it possible to generate numeric enums? #140

ottosson opened this issue Feb 6, 2023 · 9 comments
Labels
enhancement New feature or request

Comments

@ottosson
Copy link

ottosson commented Feb 6, 2023

Hi. thanks for this awesome library!

Is it possible to generate numeric enums in typescript from my rust enums?

#[derive(Serialize, Deserialize, TS, Debug)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "../src/types/interfaces/")]
pub enum PlotType {
  Display = 0,
  Extents = 1,
  Limits = 2,
  View = 3,
  Window = 4,
  Layout = 5,
}

becomes

export type PlotType = "display" | "extents" | "limits" | "view" | "window" | "layout";

I would expect it to become something like

export const enum PlotType = {
  Display = 0,
  Extents = 1,
  Limits = 2,
  View = 3,
  Window = 4,
  Layout = 5,
}

Is this possible?

@ottosson
Copy link
Author

ottosson commented Feb 8, 2023

I guess this is how enums are handled in JSON. Not an issue with ts-rs.

@ottosson ottosson closed this as completed Feb 8, 2023
@percy507
Copy link

percy507 commented Jul 4, 2023

@ottosson How do you solve this?

@ottosson
Copy link
Author

ottosson commented Jul 4, 2023

@percy507 in my case I didn't have to use the numbers really, but could use the string representation of the enum in TS. Not optimal but it works.

You can convert the enum value to number with serde so I think it should be supported by ts-rs.

@percy507
Copy link

percy507 commented Jul 4, 2023

@ottosson Thanks.

I also solve this. I don't use ts-rs. I usetsync. But I think below steps also works for ts-rs.

1. use `serde_repr` crate
2. modify the code
    - `#[derive(Serialize, Deserialize, TS, Debug)]` to `#[derive(Serialize_repr, Deserialize_repr, TS, Debug)]`

@setoelkahfi
Copy link

setoelkahfi commented Aug 6, 2024

@ottosson Thanks.

I also solve this. I don't use ts-rs. I use'tsync. But I think below steps also works for ts-rs`.

"`shell

  1. use serde_repr crate
  2. modify the code
    • #[derive(Serialize, Deserialize, TS, Debug)] to #[derive(Serialize_repr, Deserialize_repr, TS, Debug)]

@percy507 Sadly, this doesn't work. While the rust part works, the generated bindings result in the same format as the other example:

use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use ts_rs::TS;

#[derive(Serialize, Deserialize, TS, Debug)]
#[ts(export)]
pub struct ErrorResponse {
  pub error_code: ErrorCode,
  pub message: String,
}

#[repr(i32)]
#[derive(Serialize_repr, Deserialize_repr, TS, Debug)]
#[ts(export)]
pub enum ErrorCode {
    // User defined error codes starts from 1000
    UserNotFound = 1000,
    InvalidCredentials = 1001,

    // Generic error codes starts from 1
    InvalidRequest = 1,
    ParseError = 2,
    NetworkError = 3,
}

Binding:

// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type ErrorCode = "UserNotFound" | "InvalidCredentials" | "InvalidRequest" | "ParseError" | "NetworkError";

Is this possible with the current version? @ottosson, Could you reopen this issue? Otherwise, I'll open a new issue.

@gustavo-shigueo
Copy link
Collaborator

gustavo-shigueo commented Aug 6, 2024

As stated before, we really dislike TS enums (This comment is a very thorough explanation on the reasons to prefer type unions over TS enums), but we could try to figrure out some way to work with serde-repr. No idea how yet, so no promises.

In the meantime you could do

use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use ts_rs::TS;

#[derive(Serialize, Deserialize, TS, Debug)]
#[ts(export)]
pub struct ErrorResponse {
  pub error_code: ErrorCode,
  pub message: String,
}

#[repr(i32)]
#[derive(Serialize_repr, Deserialize_repr, TS, Debug)]
#[ts(export, type = "1000 | 1001 | 1 | 2 | 3")]
pub enum ErrorCode {
    // User defined error codes starts from 1000
    UserNotFound = 1000,
    InvalidCredentials = 1001,

    // Generic error codes starts from 1
    InvalidRequest = 1,
    ParseError = 2,
    NetworkError = 3,
}

Which should generate

export type ErrorCode = 1000 | 1000 | 1 | 2 | 3;

@NyxCode
Copy link
Collaborator

NyxCode commented Aug 6, 2024

Hey!

While I share @gustavo-shigueo's sentiment, i still think supporting this would be pretty cool.
Maybe we could add a #[ts(repr)], which would try to be compatible with serde_repr?
Anyways, I think now is a good time to take a 2nd look at this, after we shipped the new enum handeling.

@gustavo-shigueo
Copy link
Collaborator

Maybe we could have it as #[ts(repr = "enum")] and make that incompatible with #[ts(tag)], #[ts(content)], #[ts(type)], #[ts(as)] and any other attribute that wouldn't make sense on a TS enum. That should help us avoid having to change the enum_def and format_variant functions, which have very specific logic for dealing with tagging representations.

We could create a new enum_repr function that parses this type of enum, demanding that all variants are unit variants, with optional = number, making this a completely separate code path

@gustavo-shigueo gustavo-shigueo added the enhancement New feature or request label Aug 7, 2024
@setoelkahfi
Copy link

Hey!

While I share @gustavo-shigueo's sentiment, i still think supporting this would be pretty cool. Maybe we could add a #[ts(repr)], which would try to be compatible with serde_repr? Anyways, I think now is a good time to take a 2nd look at this, after we shipped the new enum handeling.

I don't know how this crate works internally, but in the meantime, I'm using tsync as @percy507 suggested. I use their simple #[tsync] macro, which works out of the box. I can't help with development, but I could help with testing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants