Skip to content

allow specifying return type for functions/methods when the rust side is JsValue #4377

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

Closed
rouzwelt opened this issue Dec 25, 2024 · 1 comment · Fixed by #4394
Closed

allow specifying return type for functions/methods when the rust side is JsValue #4377

rouzwelt opened this issue Dec 25, 2024 · 1 comment · Fixed by #4394

Comments

@rouzwelt
Copy link
Contributor

rouzwelt commented Dec 25, 2024

Motivation

Atm, because of rust orphan rule we cant directly implement IntoJsResult trait for a struct/type wrapper in Result<> and this issue prevents us to use typed returns on async functions as:

// `A` and `Error` both have all needed trait implementations manualy except `IntoJsResult` for a wrapped `Result<>` of them

#[derive(Serialize, Deserialize, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
struct A; // notice there is no #[wasm_bindgen] used for this struct as we just wanna get a typed obj in js/ts and not a class obj

#[wasm_bindgen]
pub fn some_function() -> Result<A, Error> {
    /// this compiles ok and works ok
};

#[wasm_bindgen]
pub async fn some_function() -> Result<A, Error> {
    /// this doesnt compile with error complaining about IntoJsResult not implemented for Result<A, Error>
};

Same situation for wrapped type of T for ReturnWasmAbi:

pub type B = Result<A, Error>

#[wasm_bindgen]
pub fn some_function() -> Result<B, Error> {
    /// this doesnt compile with error complaining about ReturnWasmAbi not implemented for Result<A, Error>
    /// and same error for async fn along with IntoJsResult error
};

Proposed Solution

  • Prefered solution (my personal choice) can be to allow custom ts return type specified like other wasm_bindgen artts like js_name, where it would apply that to the return type of the typescript generated output for an standalone fn or a class method, because this issue also effects class methods where you cant return a typed type for a single method and it ends up being any, and if you wanna override that, you'd needing to override the whole typescript of the class and all its methods using custom typescript section, instead of just being able to override that single class method. Probably this solution is easiest of the two to implement, as it would just affect the generated .d.ts as the generated js cant really type the return type of a function with a typescript defined obj type.
    So this solution can be adopted to provide typings for return types of any function and method for generated typescript for anything that returns JsValue (any in js) allowing users to fully type their output pkgs, ie functions/methods can return JsValue on rust side and handling conversion in their rust body, and still generated ts output can have a fully typed return type
#[derive(Serialize, Deserialize, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
struct SomeCustomType; // we also manually imple other wasm traits such as LongRefWasmAbi, etc without using #[wasm_bindgen]

#[wasm_bindgen(js_name = "someFn", typescript_return_type = "SomeCustomType")]
pub fn some_fn() -> JsValue {
    // fn body
}

#[wasm_bindgen]
struct A;

#[wasm_bindgen]
impl A {
    #[wasm_bindgen(js_name = "someMethod", typescript_return_type = "Promise<SomeCustomType>")]
    pub async fn some_method() -> Result<JsValue, Error> {
        // method body
    }
}
  • Another solution is to provide some macro or wrapper trait where IntoJsResult trait can be implemented for types that dont necessarily use #[wasm_bindgen] on their declaration but implement wasm traits manualy, so that they can be returned from async function as well. Note that this solution most probably cant handle every usecase and situations.
    that would be:
// need some way to be able to implement this for a type individually just like any other wasm trait
// ideally need this to be impl the same for wrapped types of T such as Vec<T>, Option<T>, etc as well
impl<T: Into<JsValue>, E: Into<JsValue>> IntoJsResult for Result<T, E>

same goes for ReturnWasmAbi for wrapped types of <T, E>.

Alternatives

Atm the only workaround for this that I know of is to use custom typescript section to handcode the typescript for the given fn, so its return type is typed on the final .d.ts output

@rouzwelt rouzwelt changed the title allow manual/standalone implementation for IntoJsResult for types without using #[wasm_bindgen] allow manual/standalone implementation for IntoJsResult for types and ReturnWasmAbi for wrapped types without using #[wasm_bindgen] Dec 25, 2024
@rouzwelt rouzwelt changed the title allow manual/standalone implementation for IntoJsResult for types and ReturnWasmAbi for wrapped types without using #[wasm_bindgen] allow specifying return type for functions/methods when the rust side is JsValue Dec 25, 2024
@daxpedda
Copy link
Collaborator

Duplicate of #1847.

But yes, I'm generally in favor of adding support to this via attributes.

@daxpedda daxpedda closed this as not planned Won't fix, can't repro, duplicate, stale Dec 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants