- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Typescript Generic Types #4455
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
base: main
Are you sure you want to change the base?
Typescript Generic Types #4455
Conversation
any @maintainers here? |
@daxpedda hey there, sorry to ping you, this PR has been waiting on a review for some time now, would be nice if you or any other maintainers can take a look at it. |
@alexcrichton @fitzgen hey guys, would be nice to get a review on this whenever you guys got some time. |
@alexcrichton @fitzgen @daxpedda hey guys, would be nice if someone can take a look at this PR and maybe we can settle this, I think it would be a really good improvement that many would need/benefit from |
@alexcrichton @fitzgen @daxpedda hey guys, it would be really nice if we can work this PR out together, looking forward to your response |
@rouzwelt new maintainer here, this is an interesting direction, I would like to review it more carefully soon. It would be great if you could be clear about the limitations of the approach as well. |
Motivation
resolves #4451
Currently if a function/method has a generic return or arguments type like:
where
SomeType
is just plain struct that impls wasm traits manually (not using wasm_bindgen macro on its definition, ie not js class) the generated typescript bindings wont correctly map the generic types and doesnt actually include them:Although user can use
unchecked_return_type
andunchecked_param_type
attribute to specify them, but this is not really ideal, it is fine and ok if there are a couple of functions to apply those attrs to, but if there are tons of functions and methods, it wont really end up good as they are unchecked and bug prone, however if the nested types can be processed regularly like the main type, this can simply be resolved, so on typescript we would get:Proposed Solution
Implement some logic to parse and map the types deeply, possibly recursively, until all nested types are parsed and accounted for in generated typescript.
There is a mapper currently that maps the rust return types to their equivalent js/ts types, but looks like it just checks 1 level deep, and doesnt go deeper than that, however with some tweaks, the same logic can be applied on nested types to correctly map the return type for the js/ts bindings.
We need to parse the args/return
syn::Type
s separately and map them with their nestedsyn::Type
s into their correspondingWasmDescribe
which later on can be encoded and then decoded intoDescriptor
and next intoAdapterType
so can be appended lastly to the parent TS type as generic if they happen to be generic.High-Level Implementation Details
We we would use native encoded/decoded
WasmDescribe::inform()
for return and arguments types, meaning we will encode their wasm informs in thebackend::codegen
forExport
and then decode it atcli-support::descriptor::Function
which now has 2 new more fields:inner_ret_map
andargs_ty_map
, these 2 field hold theDescriptor
which now has 1 more variant calledDescriptor::Generic
which exclusively added for this purpose and doesnt have any effect on any previous functionalities:that can hold the type map for both args and return type, now at
cli-support::wit::register_export_adapter
we convert thoseinner_ret_map
andargs_ty_map
fields intoAdapterType
using a newly added function calleddescribe_map_to_adapter
where it just maps the givenDescriptor
to itsAdapterType
by also handling of nested generic types.Lastly when building the ts signature and js doc for the binding function/method, we will convert those generic
AdapterType
s into their corresponding js/ts types and append them to the main parent type.New tests are added under
typescript-tests
crate testing complex nested generic types to be correctly mapped to their ts signature.This feature doesnt change any of the previous functionalities and logic, it simply is a new piece of logic that separately maps a
syn::Type
with any of its nestedsyn::Type
s to theirWasmDescribe
and thenDescriptor
and after that toAdapterType
completely separate to the how args and return type are resolved, and at the very last step of generating the ts signature, if the arg/return type is a generic, it will just append the generic to the actual parent type.Note
An attribute can be added to be able to turn this off for a given function/method, I have not added such attribute in this PR, but if that's desired, I can add it.