-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Setting Typescript types for returned duck-typed objects. #1591
Comments
Seems like a reasonable feature to me! |
Currently you can just return a Rust struct, like so: #[wasm_bindgen]
pub struct Foo {
pub width: f64,
pub height: f64,
}
#[wasm_bindgen]
pub fn jpeg_image_size(image: &[u8]) -> Foo {
let (width, height): (u32, u32) = unimplemented!();
Foo { width, height }
} This also generates correct TypeScript types. The only issue is it creates a JS #[wasm_bindgen(plain_object)]
pub struct Foo {
pub width: f64,
pub height: f64,
} (Obviously methods wouldn't work on it, and there's some subtlety around |
Any progress? What if using Depends on chapter 2.9: /// exports type `Pink` to `.d.ts`
#[wasm_bindgen(typescript_custom_section)]
const TS_APPEND_CONTENT: &'static str = r#"
export type Pink = { "whoami": string };
"#;
/// duck-type interface
#[wasm_bindgen]
extern "C" {
pub type Foo;
#[wasm_bindgen(structural, method, getter)]
pub fn width(this: &Foo) -> String;
#[wasm_bindgen(structural, method, getter)]
pub fn height(this: &Foo) -> String;
}
/// generate `Foo` to `.d.ts`
#[wasm_bindgen]
pub fn jpeg_image_size(image: &[u8]) -> Foo {
let (width, height): (u32, u32) = unimplemented!();
Foo { width, height }
} |
I'd moved on from this long ago, following @Pauan's suggestion I believe. I'd tackle this now that you've reminded me, but I'm not familiar with the wasm-bindgen code or have a lot of time to invest in it. I don't think it'd be hard to do in any case, it'd probably qualify as a good first issue. |
@andreubotella Thanks for ur advice, this is a good entry for me to contribute to |
Since the plain-object won't work with Vecs, I'd rather having something like struct Bar { ... }
struct Foo {
bars: Vec<Bar>
}
#[wasm_bindgen]
fn foo() -> JsValue<Foo> {
//
} interface Bar {
...
}
interface Foo {
bars: Array<Bar>
}
foo(): Foo; |
For me, the first-prize solution would be for us to be able to declare the a struct can be marshalled to Javascript in one direction, only. For example:
This would have the same effect, conceptually, as making the
Additional benefits:
|
I appreciate @clearloop's contribution to this issue. The problem, however, is that we still cannot use #[wasm_bindgen(typescript_custom_section)]
const TS_APPEND_CONTENT: &'static str = r#"
type DatasourceDbURL
= { static: string }
| { env: string }
"#;
#[wasm_bindgen(typescript_type = "DatasourceDb")]
pub enum DatasourceDbURL {
Static(String),
// ^^^^^^^^^^^^^^
// only C-Style enums allowed with #[wasm_bindgen]
Env(String),
} |
I'd like to return a Set<number> |
A decent workaround to this is to skip automatically emitting the type and add it manually. This is error-prone but not too much boilerplate. // Define TypeScript interfaces for your serializable types.
#[wasm_bindgen(typescript_custom_section)]
const TYPES: &str = r###"
interface Position {
x: number,
y: number,
}
"###;
#[wasm_bindgen]
pub struct Step(...);
#[wasm_bindgen]
impl Step {
// Apply skip_typescript to the methods that return JsValue.
#[wasm_bindgen(skip_typescript)]
pub fn trace(&mut self) -> JsValue {
serde_wasm_bindgen::to_value(&self.0.trace()).unwrap()
}
}
// Manually add the method to the interface.
#[wasm_bindgen(typescript_custom_section)]
const STEP_TYPES: &str = r###"
export interface Step {
trace(): Position[];
}
"###; Hopefully we can get proper support for emitting proper types for these "JSON" values soon. |
Motivation
As far as I understand, the only way to return an object with a duck-typed interface from Rust to JS for the time being is to build it by reflection and return it as a
JsValue
. The generated Typescript definition rightfully gives the returned type asany
, which does its job, but it fails to convey the author's intentions. A better solution would be to add a way to declare a Typescript type for a returned JsValue.Proposed Solution
The proposed solution would be to add a
wasm_bindgen
attribute, perhaps called something likereturn_typescript_type
, containing a Typescript type. Any named references contained in the type must be defined elsewhere in atypescript_custom_section
, although parsing the TS to ensure that might not be a priority.Alternatives
Hopefully sometime in the future,
wasm_bindgen
will offer a way to return duck-typed interfaces from Rust without reflection, which would provide the necessary types for the TS declaration to be reasonably complete by default.The text was updated successfully, but these errors were encountered: