tsify icon indicating copy to clipboard operation
tsify copied to clipboard

Internally tagged enums can generate invalid TS when using non-object types

Open Alfred-Mountfield opened this issue 2 years ago • 1 comments

If you have an enum such as this:

#[derive(Debug, Serialize, Deserialize, Tsify)]
#[serde(tag = "reason")]
pub enum ParseBaseUriError {
    MissingTrailingSlash,
    UrlParseError(String),
    CannotBeABase,
}

then the generated types look as follows:

declare namespace ParseBaseUriError {
    export type MissingTrailingSlash = { reason: "MissingTrailingSlash" };
    export type UrlParseError = { reason: "UrlParseError" } & string;
    export type CannotBeABase = { reason: "CannotBeABase" };
}

And I believe UrlParseError is unsatisfiable.

I don't really have a good suggestion for how to resolve this, perhaps disallowing new-type like variants, or possibly only ones that contain types that can be mapped to a non-object JS type. For now I have resolved this by picking a different tagging mechanism, or turning the variants into structs, but I thought I'd flag in case there are any other ideas or to allow adding a warning.

Alfred-Mountfield avatar Aug 29 '22 09:08 Alfred-Mountfield

I have also noted the same issue, which can quickly be avoided by using both tag and content, e.g., something like #[serde(tag = "_tag", content = "value")]. With your example above:

#[derive(Debug, Serialize, Deserialize, Tsify)]
#[serde(rename_all = "camelCase", tag = "_tag", content = "value")]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub enum ParseBaseUriError {
  MissingTrailingSlash,
  UrlParseError(String),
  CannotBeABase,
}

results in the following type declaration:

// you can pattern-match on the `_tag` property
export type ParseBaseUriError
  = { _tag: "missingTrailingSlash" }
  | { _tag: "urlParseError", value: string }
  | { _tag: "cannotBeABase" }

jkomyno avatar Oct 16 '22 09:10 jkomyno