Skip to content
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

Add null to argument types of optional parameters #4188

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
* String enums now generate private TypeScript types but only if used.
[#4174](https://github.com/rustwasm/wasm-bindgen/pull/4174)

* Optional parameters are now typed as `T | undefined | null` to reflect the actual JS behavior.
daxpedda marked this conversation as resolved.
Show resolved Hide resolved
[#4188](https://github.com/rustwasm/wasm-bindgen/pull/4188)

### Fixed

* Fixed methods with `self: &Self` consuming the object.
Expand Down
36 changes: 28 additions & 8 deletions crates/cli-support/src/js/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,13 +312,14 @@ impl<'a, 'b> Builder<'a, 'b> {
let mut ts = String::new();
match ty {
AdapterType::Option(ty) if omittable => {
// e.g. `foo?: string | null`
arg.push_str("?: ");
adapter2ts(ty, &mut ts, Some(&mut ts_refs));
adapter2ts(ty, TypePosition::Argument, &mut ts, Some(&mut ts_refs));
}
ty => {
omittable = false;
arg.push_str(": ");
adapter2ts(ty, &mut ts, Some(&mut ts_refs));
adapter2ts(ty, TypePosition::Argument, &mut ts, Some(&mut ts_refs));
}
}
arg.push_str(&ts);
Expand Down Expand Up @@ -354,7 +355,12 @@ impl<'a, 'b> Builder<'a, 'b> {
let mut ret = String::new();
match result_tys.len() {
0 => ret.push_str("void"),
1 => adapter2ts(&result_tys[0], &mut ret, Some(&mut ts_refs)),
1 => adapter2ts(
&result_tys[0],
TypePosition::Return,
&mut ret,
Some(&mut ts_refs),
),
_ => ret.push_str("[any]"),
}
if asyncness {
Expand Down Expand Up @@ -386,7 +392,7 @@ impl<'a, 'b> Builder<'a, 'b> {
for (name, ty) in fn_arg_names.iter().zip(arg_tys).rev() {
let mut arg = "@param {".to_string();

adapter2ts(ty, &mut arg, None);
adapter2ts(ty, TypePosition::Argument, &mut arg, None);
arg.push_str("} ");
match ty {
AdapterType::Option(..) if omittable => {
Expand All @@ -407,7 +413,7 @@ impl<'a, 'b> Builder<'a, 'b> {

if let (Some(name), Some(ty)) = (variadic_arg, arg_tys.last()) {
ret.push_str("@param {...");
adapter2ts(ty, &mut ret, None);
adapter2ts(ty, TypePosition::Argument, &mut ret, None);
ret.push_str("} ");
ret.push_str(name);
ret.push('\n');
Expand Down Expand Up @@ -1428,7 +1434,18 @@ impl Invocation {
}
}

fn adapter2ts(ty: &AdapterType, dst: &mut String, refs: Option<&mut HashSet<TsReference>>) {
#[derive(Debug, Clone, Copy)]
enum TypePosition {
Argument,
Return,
}

fn adapter2ts(
ty: &AdapterType,
position: TypePosition,
dst: &mut String,
refs: Option<&mut HashSet<TsReference>>,
) {
match ty {
AdapterType::I32
| AdapterType::S8
Expand All @@ -1446,8 +1463,11 @@ fn adapter2ts(ty: &AdapterType, dst: &mut String, refs: Option<&mut HashSet<TsRe
AdapterType::Bool => dst.push_str("boolean"),
AdapterType::Vector(kind) => dst.push_str(&kind.js_ty()),
AdapterType::Option(ty) => {
adapter2ts(ty, dst, refs);
dst.push_str(" | undefined");
adapter2ts(ty, position, dst, refs);
dst.push_str(match position {
TypePosition::Argument => " | undefined | null",
RunDevelopment marked this conversation as resolved.
Show resolved Hide resolved
TypePosition::Return => " | undefined",
});
}
AdapterType::NamedExternref(name) => dst.push_str(name),
AdapterType::Struct(name) => dst.push_str(name),
Expand Down
185 changes: 185 additions & 0 deletions crates/cli/tests/reference/echo.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/* tslint:disable */
/* eslint-disable */
/**
* @param {number} a
* @returns {number}
*/
export function echo_u8(a: number): number;
/**
* @param {number} a
* @returns {number}
*/
export function echo_i8(a: number): number;
/**
* @param {number} a
* @returns {number}
*/
export function echo_u16(a: number): number;
/**
* @param {number} a
* @returns {number}
*/
export function echo_i16(a: number): number;
/**
* @param {number} a
* @returns {number}
*/
export function echo_u32(a: number): number;
/**
* @param {number} a
* @returns {number}
*/
export function echo_i32(a: number): number;
/**
* @param {bigint} a
* @returns {bigint}
*/
export function echo_u64(a: bigint): bigint;
/**
* @param {bigint} a
* @returns {bigint}
*/
export function echo_i64(a: bigint): bigint;
/**
* @param {number} a
* @returns {number}
*/
export function echo_usize(a: number): number;
/**
* @param {number} a
* @returns {number}
*/
export function echo_isize(a: number): number;
/**
* @param {number} a
* @returns {number}
*/
export function echo_f32(a: number): number;
/**
* @param {number} a
* @returns {number}
*/
export function echo_f64(a: number): number;
/**
* @param {boolean} a
* @returns {boolean}
*/
export function echo_bool(a: boolean): boolean;
/**
* @param {string} a
* @returns {string}
*/
export function echo_char(a: string): string;
/**
* @param {string} a
* @returns {string}
*/
export function echo_string(a: string): string;
/**
* @param {Uint8Array} a
* @returns {Uint8Array}
*/
export function echo_vec_u8(a: Uint8Array): Uint8Array;
/**
* @param {Foo} a
* @returns {Foo}
*/
export function echo_struct(a: Foo): Foo;
/**
* @param {(Foo)[]} a
* @returns {(Foo)[]}
*/
export function echo_vec_struct(a: (Foo)[]): (Foo)[];
/**
* @param {number | undefined | null} [a]
* @returns {number | undefined}
*/
export function echo_option_u8(a?: number): number | undefined;
RunDevelopment marked this conversation as resolved.
Show resolved Hide resolved
/**
* @param {number | undefined | null} [a]
* @returns {number | undefined}
*/
export function echo_option_i8(a?: number): number | undefined;
/**
* @param {number | undefined | null} [a]
* @returns {number | undefined}
*/
export function echo_option_u16(a?: number): number | undefined;
/**
* @param {number | undefined | null} [a]
* @returns {number | undefined}
*/
export function echo_option_i16(a?: number): number | undefined;
/**
* @param {number | undefined | null} [a]
* @returns {number | undefined}
*/
export function echo_option_u32(a?: number): number | undefined;
/**
* @param {number | undefined | null} [a]
* @returns {number | undefined}
*/
export function echo_option_i32(a?: number): number | undefined;
/**
* @param {bigint | undefined | null} [a]
* @returns {bigint | undefined}
*/
export function echo_option_u64(a?: bigint): bigint | undefined;
/**
* @param {bigint | undefined | null} [a]
* @returns {bigint | undefined}
*/
export function echo_option_i64(a?: bigint): bigint | undefined;
/**
* @param {number | undefined | null} [a]
* @returns {number | undefined}
*/
export function echo_option_usize(a?: number): number | undefined;
/**
* @param {number | undefined | null} [a]
* @returns {number | undefined}
*/
export function echo_option_isize(a?: number): number | undefined;
/**
* @param {number | undefined | null} [a]
* @returns {number | undefined}
*/
export function echo_option_f32(a?: number): number | undefined;
/**
* @param {number | undefined | null} [a]
* @returns {number | undefined}
*/
export function echo_option_f64(a?: number): number | undefined;
/**
* @param {boolean | undefined | null} [a]
* @returns {boolean | undefined}
*/
export function echo_option_bool(a?: boolean): boolean | undefined;
/**
* @param {string | undefined | null} [a]
* @returns {string | undefined}
*/
export function echo_option_char(a?: string): string | undefined;
/**
* @param {string | undefined | null} [a]
* @returns {string | undefined}
*/
export function echo_option_string(a?: string): string | undefined;
/**
* @param {Uint8Array | undefined | null} [a]
* @returns {Uint8Array | undefined}
*/
export function echo_option_vec_u8(a?: Uint8Array): Uint8Array | undefined;
/**
* @param {Foo | undefined | null} [a]
* @returns {Foo | undefined}
*/
export function echo_option_struct(a?: Foo): Foo | undefined;
/**
* @param {(Foo)[] | undefined | null} [a]
* @returns {(Foo)[] | undefined}
*/
export function echo_option_vec_struct(a?: (Foo)[]): (Foo)[] | undefined;
export class Foo {
free(): void;
}
Loading