Is there any way to annotate the TypeScript type of wasm-bindgen's JsValue to something more meaningful?

I have a Rust / Wasm function that I am generating TypeScript bindings for using wasm_bindgen. The output type for JsValue is any . Is there any way to manually annotate the type to something more meaningful without editing the auto-generated *.d.ts ?

    #[wasm_bindgen]
    impl GameClient {
        pub fn game_list(&self) -> JsValue {
            JsValue::from_serde(&self.game_list).unwrap()
        }
    }

Do you have to generate the JsValue in the Rust code and not the struct you need? AFAIK wasm-bindgen simply maps Rust types to TypeScript types.

wasm_bindgen was unable to safely convert the struct into a JS object, forcing me to serialize and deserialize it.

Well, then - could you share the struct definition? Maybe we can, instead of (de)serializing, convert it to/from some other struct, which would be then used by wasm-bindgen?

Okay, here are the definitions for game_list:

#[wasm_bindgen]
pub struct GameClient{
    game_list: Vec<GameMetadata>
}

//#[wasm_bindgen] <- will not work because String is not copy.
#[derive(Deserialize, Serialize, Clone)]
pub struct GameMetadata {
    pub game_id: String
}

#[wasm_bindgen]
pub struct GameClient {
    game_list: Vec<GameMetadata>
}

// #[wasm_bindgen] <- Will not work because Vec<T> is not supported.
impl GameClient {
    pub fn game_list(&self) -> Vec<GameMetadata> {
        self.game_list.clone()
    }
}

Both the Vec and the string are problems that don’t have obvious solutions.

Also, I feel like while my particular example might be better solved by other solutions, I can see many usecases where writing conversion code for complex data structures isn’t worth the effort and seralization is the best route, meaning that the original question still would benefit from an answer.

According to docs, String should be supported. Vec seems to be harder, however: we could try to send the boxed slices on the JS side, but I can’t find any obvious way to convert it back to Vec without reallocation.

Strings are not supported as struct members, because they do not implement Copy. Luckily this data transfer is one way, so I don’t need to go from JS into vector, so a boxed slice sounds reasonable assuming I can get it to work. Anyway, an allocation is definitely better than deserliaization in terms of performance which is great.