Skip to content

Support for ? Suffix in TypeScript Definitions for Optional Parameters with #[wasm_bindgen(unchecked_param_type)] #4412

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

Open
cptpiepmatz opened this issue Jan 20, 2025 · 1 comment

Comments

@cptpiepmatz
Copy link

Motivation

I'm using the new #[wasm_bindgen(unchecked_param_type)] from #4394 for an options object which is optional. But that seems to come with some issues.

Let's say we have a function like this:

#[wasm_bindgen]
pub fn f(
    #[wasm_bindgen(unchecked_param_type = "MyOptions | undefined")]
    options: Option<js_sys::Object>
) {...}

The intention here should be clear: f is a function that takes an optional parameter of type MyOptions, which is included via some other means.

However, the output of this function in the TypeScript definitions would be:

export function f(options: MyOptions | undefined): void;

This is missing the ? suffix that is usually available for other optional values. Normally, it would generate:

export function f(options?: object | null): void;

without the param type override.

I would really like to have it generate:

export function f(options?: MyOptions | null): void;

Proposed Solution

I see three options here:

  1. Inspect the Param Type in #[wasm_bindgen(unchecked_param_type)]
    Allow the attribute to inspect the param type, and when it's Option, add the ? suffix. However, this would only work for types that implement OptionFromWasmAbi, which JsValue does not implement. This limitation would make the attribute less useful overall.

  2. Modify #[wasm_bindgen(unchecked_param_type)] to Accept a Parameter
    Add a parameter, such as ?, to declare the param as optional. While this approach is flexible, it feels unintuitive because it adds complexity to the attribute's syntax.

  3. Add a New Attribute
    Introduce a new attribute, such as #[wasm_bindgen(unchecked_optional_param)], to explicitly mark a parameter as optional. This would be straightforward and would work even with JsValue, as you could simply check for JsValue::is_undefined to determine whether the value is set.

I believe the third option, adding #[wasm_bindgen(unchecked_optional_param)], is the most flexible and intuitive. It would address the issue without relying on the param type or modifying existing behavior.

Alternatives

It may be possible to define overloaded functions using the #[wasm_bindgen(js_name)] attribute. However, now you have two function signatures, and you would need to duplicate your documentation to make it available at all relevant positions.

I also tried passing a default value into the #[wasm_bindgen(unchecked_param_type)] call to trick TypeScript, but that doesn't work for .d.ts files.

Additional Context

Modern JavaScript libraries commonly use this structure when all fields in an options object are optional. Examples include:

@cptpiepmatz
Copy link
Author

Also I would like to help out here and implement this feature if this wanted and we have a clear selection how the API should look like.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant