tsify icon indicating copy to clipboard operation
tsify copied to clipboard

Is it possible to generate a TS ambient enum?

Open hillin opened this issue 2 years ago • 2 comments

Edit: I'm generalizing this issue.

Currently all rust enums are generated as typescript union types. While this is perfectly valid as rust enums are literally discriminated unions, sometimes we'd expect plain old enums in the declaration file. Apparently the d.ts way is to use ambient enum. Can we do this with tsify?

Original issue: Title: Is it possible to generate a TS string enum? String enum in Typescript: https://www.typescriptlang.org/docs/handbook/enums.html#string-enums

hillin avatar Jun 27 '23 09:06 hillin

I've also bumped in this issue. To get C-style / ambient enum declarations, you'd need the serde_repr crate and something like:

use serde_repr::{Deserialize_repr};

#[derive(Debug, PartialEq, Eq, Deserialize_repr, Tsify)]
#[tsify(from_wasm_abi)]
#[repr(u8)]
pub enum AmbientEnum {
    Int32 = 0,
    Int64 = 1,
}

This way, you'd get the correct Rust deserialization logic:

#[wasm_bindgen_test]
fn ambient_enum_test() {
    // Example deserialization code
    let json_data = r#"0"#;
    let n_value = serde_json::from_str::<u32>(&json_data).unwrap();
    let n_value = serde_json::from_str::<i32>(&json_data).unwrap();
    let n_value = serde_json::from_str::<u64>(&json_data).unwrap();
    let n_value = serde_json::from_str::<i64>(&json_data).unwrap();

    let ambient_enum = serde_json::from_str::<AmbientEnum>(&json_data).unwrap();
    assert_eq!(ambient_enum, AmbientEnum::Int32);
}

However, tsify would be confused about the types, and would generate

export type AmbientEnum = "Int32" | "Int64";

rather than

export enum AmbientEnum {
  Int32 = 0,
  Int64 = 1,
}

@madonoharu would you have opinionated ideas about how to solve this? Should tsify be able to recognise #[repr(u8)] declarations on enums, and apply different type generations as per the example above?

jkomyno avatar Nov 23 '23 12:11 jkomyno

This is the same use case I stumbled upon, thank you all for sharing such examples. Even if not strictly the same, as a workaround I used enum with namespace.

AndreaScn avatar Apr 12 '24 09:04 AndreaScn