ts-rs icon indicating copy to clipboard operation
ts-rs copied to clipboard

Feature request: #[ts(repr(enum)) enhancement

Open eythaann opened this issue 3 months ago • 2 comments

#[ts(repr(enum)) was a good addition to the project on last version, but when using #[ts(repr(enum = name)) and serde rename it takes the renamed value as key and as value, I think the key should be the same as used on Rust side and only change the value.

This is a quality of life, as the enum usage and values will be the same on rust and ts sides.

Example:

#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, TS)]
#[serde(rename_all = "kebab-case")]
#[ts(repr(enum = name))]
pub enum MixBlendMode {
    Normal,
    #[default]
    Multiply,
    Screen,
    Overlay,
    Darken,
    Lighten,
    ColorDodge,
    ColorBurn,
    HardLight,
    SoftLight,
    Difference,
    Exclusion,
    Hue,
    Saturation,
    Color,
    Luminosity,
    PlusDarker,
    PlusLighter,
}

Current Behavior:

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

export enum MixBlendMode {
  "normal" = "normal",
  "multiply" = "multiply",
  "screen" = "screen",
  "overlay" = "overlay",
  "darken" = "darken",
  "lighten" = "lighten",
  "color-dodge" = "color-dodge",
  "color-burn" = "color-burn",
  "hard-light" = "hard-light",
  "soft-light" = "soft-light",
  "difference" = "difference",
  "exclusion" = "exclusion",
  "hue" = "hue",
  "saturation" = "saturation",
  "color" = "color",
  "luminosity" = "luminosity",
  "plus-darker" = "plus-darker",
  "plus-lighter" = "plus-lighter",
}

Rust: MixBlendMode.ColorDodge Typescript: MixBlendMode["color-dodge"]

Expected Behavior:

export enum MixBlendMode {
  "Normal" = "normal",
  "Multiply" = "multiply",
  "Screen" = "screen",
  "Overlay" = "overlay",
  "Darken" = "darken",
  "Lighten" = "lighten",
  "ColorDodge" = "color-dodge",
  "ColorBurn" = "color-burn",
  "HardLight" = "hard-light",
  "SoftLight" = "soft-light",
  "Difference" = "difference",
  "Exclusion" = "exclusion",
  "Hue" = "hue",
  "Saturation" = "saturation",
  "Color" = "color",
  "Luminosity" = "luminosity",
  "PlusDarker" = "plus-darker",
  "PlusLighter" = "plus-lighter",
}

Rust: MixBlendMode.ColorDodge Typescript: MixBlendMode.ColorDodge

eythaann avatar Oct 15 '25 22:10 eythaann

Hi @eythaann, thanks for the issue! This is a very interesting idea, and it would make a lot of sense to make the usage of an enum the same in both languages, though I wonder what this means for integer enums:

  • Do we make rename_all affect only the value for repr(enum = name) and the key for repr(enum)? This seems like it'd cause confusion due to the inconsistent behavior
  • Do we disable rename_all for integer enums for consistency? This would likely annoy some people and result in several issues asking to enable rename_all for them
  • Do we keep it as is, forcing the user to have different access syntax between the two languages (most notably having to use ["my-key"] for kebab-case)?

@NyxCode do you have any thoughts?

gustavo-shigueo avatar Oct 16 '25 11:10 gustavo-shigueo

Some extra points:

  • As default serde convert the enums to String values, so repr(enum) by default should be the current repr(enum = name) like on serialization unless code using some crate to serialize enums into intergers.
  • This crate represents the value types, currently we use the same name of structs in Rust and TS, so having the same name for enums keys is in order with the rest of behaviors, as the important representation of the type is on the string literal or number literal value of the enum.

eythaann avatar Oct 17 '25 02:10 eythaann