-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Enum impl fn gives name conflict error #1715
Comments
I'm running in to this as well using version 0.2.60 , is there a workaround for it? |
The code to fix here is likely around |
The problem seems to be that the class gets generated twice here:
Enum's are currently generated as JS objects like this: What is the JS we expect to generate for methods on enums? |
I don't know what the expected JS for this is, it may be the case that JS doesn't support methods-on-enums. |
@alexcrichton Enums don't exist in JavaScript at all. They do exist in TypeScript, but they do not support methods at all, they are just simple C-style enums. For example, this... enum Foo {
Bar,
Qux,
Corge,
} ...gets compiled by TypeScript into this: (function (Foo) {
Foo[Foo["Bar"] = 0] = "Bar";
Foo[Foo["Qux"] = 1] = "Qux";
Foo[Foo["Corge"] = 2] = "Corge";
})(Foo || (Foo = {})); This is very similar to what wasm-bindgen currently generates. TypeScript also supports "ADT-style" enums, which look like this: type Foo
= { type: "bar", value: number }
| { type: "qux" }
| { type: "corge", first: string, second: string }; These are translated into normal JS objects (e.g. |
I think this is perhaps an issue we can't fix then? We can likely provide a better error message but methods-on-enums may just not be supported. |
Yeah, I don't see any good ways to support methods on enums:
We definitely should have a better error message though. |
As far as users are concerned, the solution for them is to export regular functions (not methods), like this: #[wasm_bindgen]
#[derive(Copy, Clone)]
pub enum ImageFormat {
PNG,
JPEG,
GIF,
}
#[wasm_bindgen]
pub fn from_str(s: &str) -> Result<ImageFormat, JsValue> {
match s {
"PNG" => Ok(ImageFormat::PNG),
"JPEG" => Ok(ImageFormat::JPEG),
"GIF" => Ok(ImageFormat::GIF),
_ => Err(JsValue::from(js_sys::Error::new(&format!("Unknown format: {}", s)))),
}
}
#[wasm_bindgen]
pub fn foo(x: ImageFormat) {
// ...
} Now everything works fine, both in the code generation and the TypeScript types. |
I think we could support "static" methods using export enum ImageFormat {
PNG, JPEG, GIF
}
export namespace ImageFormat {
export function fromStr(s: string): ImageFormat {
if (s === "PNG") return ImageFormat.PNG;
if (s === "JPEG") return ImageFormat.JPEG;
if (s === "GIF") return ImageFormat.GIF;
throw new Error("Unknown format: " + s);
}
} The TypeScript compiler generates the following JS and D.TS files for this: export var ImageFormat;
(function (ImageFormat) {
ImageFormat[ImageFormat["PNG"] = 0] = "PNG";
ImageFormat[ImageFormat["JPEG"] = 1] = "JPEG";
ImageFormat[ImageFormat["GIF"] = 2] = "GIF";
})(ImageFormat || (ImageFormat = {}));
(function (ImageFormat) {
function fromStr(s) {
if (s === "PNG") return ImageFormat.PNG;
if (s === "JPEG") return ImageFormat.JPEG;
if (s === "GIF") return ImageFormat.GIF;
throw new Error("Unknown format: " + s);
}
ImageFormat.fromStr = fromStr;
})(ImageFormat || (ImageFormat = {})); export declare enum ImageFormat {
PNG = 0,
JPEG = 1,
GIF = 2
}
export declare namespace ImageFormat {
function fromStr(s: string): ImageFormat;
} So supporting enum methods that don't use For those curious, TS is quite smart in differentiating between the enum |
But then it seems to me that neither JS or TS has proper support for something like this and we are just polyfilling it. This begs the question: why? However, the current error situation could definitely be improved, so that should be fixed. Let me know if I misunderstood anything. |
I mean, JS doesn't have a concept of enums in the first place, but you are correct in that TS has no specific language feature/syntax for this. However, adding static members to Note: TS namespaces predate ESM and were originally intended to scope/namespace classes/functions/etc. to compensate for the lack of modules in JS. Today, the docs even recommend that you don't use namespaces for modules in modern code. AFAIK, the primary use case namespaces today is to organize types in |
Right, I was thinking that this concerns support for classes as well, but forgot that this is already supported because static methods are a thing in JS.
Thank you, this is quite convincing to me. I'm happy to review a PR. |
Based on the comment at #1496 (comment), this gives an error:
The error is:
The
wasm-bindgen
version in my lock file is0.2.48
.The text was updated successfully, but these errors were encountered: