Skip to content

Commit f931112

Browse files
Add null to argument types of optional parameters (#4188)
1 parent 720b9fe commit f931112

15 files changed

+211
-103
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
# `wasm-bindgen` Change Log
22
--------------------------------------------------------------------------------
33

4+
## Unreleased
5+
6+
### Changed
7+
8+
* Optional parameters are now typed as `T | undefined | null` to reflect the actual JS behavior.
9+
[#4188](https://github.com/rustwasm/wasm-bindgen/pull/4188)
10+
11+
--------------------------------------------------------------------------------
12+
413
## [0.2.99](https://github.com/rustwasm/wasm-bindgen/compare/0.2.98...0.2.99)
514

615
Released 2024-12-07

crates/cli-support/src/js/binding.rs

+33-10
Original file line numberDiff line numberDiff line change
@@ -321,13 +321,15 @@ impl<'a, 'b> Builder<'a, 'b> {
321321
let mut ts = String::new();
322322
match ty {
323323
AdapterType::Option(ty) if omittable => {
324+
// e.g. `foo?: string | null`
324325
arg.push_str("?: ");
325-
adapter2ts(ty, &mut ts, Some(&mut ts_refs));
326+
adapter2ts(ty, TypePosition::Argument, &mut ts, Some(&mut ts_refs));
327+
ts.push_str(" | null");
326328
}
327329
ty => {
328330
omittable = false;
329331
arg.push_str(": ");
330-
adapter2ts(ty, &mut ts, Some(&mut ts_refs));
332+
adapter2ts(ty, TypePosition::Argument, &mut ts, Some(&mut ts_refs));
331333
}
332334
}
333335
arg.push_str(&ts);
@@ -363,7 +365,12 @@ impl<'a, 'b> Builder<'a, 'b> {
363365
let mut ret = String::new();
364366
match result_tys.len() {
365367
0 => ret.push_str("void"),
366-
1 => adapter2ts(&result_tys[0], &mut ret, Some(&mut ts_refs)),
368+
1 => adapter2ts(
369+
&result_tys[0],
370+
TypePosition::Return,
371+
&mut ret,
372+
Some(&mut ts_refs),
373+
),
367374
_ => ret.push_str("[any]"),
368375
}
369376
if asyncness {
@@ -395,16 +402,18 @@ impl<'a, 'b> Builder<'a, 'b> {
395402
for (name, ty) in fn_arg_names.iter().zip(arg_tys).rev() {
396403
let mut arg = "@param {".to_string();
397404

398-
adapter2ts(ty, &mut arg, None);
399-
arg.push_str("} ");
400405
match ty {
401-
AdapterType::Option(..) if omittable => {
406+
AdapterType::Option(ty) if omittable => {
407+
adapter2ts(ty, TypePosition::Argument, &mut arg, None);
408+
arg.push_str(" | null} ");
402409
arg.push('[');
403410
arg.push_str(name);
404411
arg.push(']');
405412
}
406413
_ => {
407414
omittable = false;
415+
adapter2ts(ty, TypePosition::Argument, &mut arg, None);
416+
arg.push_str("} ");
408417
arg.push_str(name);
409418
}
410419
}
@@ -416,7 +425,7 @@ impl<'a, 'b> Builder<'a, 'b> {
416425

417426
if let (Some(name), Some(ty)) = (variadic_arg, arg_tys.last()) {
418427
ret.push_str("@param {...");
419-
adapter2ts(ty, &mut ret, None);
428+
adapter2ts(ty, TypePosition::Argument, &mut ret, None);
420429
ret.push_str("} ");
421430
ret.push_str(name);
422431
ret.push('\n');
@@ -1542,7 +1551,18 @@ impl Invocation {
15421551
}
15431552
}
15441553

1545-
fn adapter2ts(ty: &AdapterType, dst: &mut String, refs: Option<&mut HashSet<TsReference>>) {
1554+
#[derive(Debug, Clone, Copy)]
1555+
enum TypePosition {
1556+
Argument,
1557+
Return,
1558+
}
1559+
1560+
fn adapter2ts(
1561+
ty: &AdapterType,
1562+
position: TypePosition,
1563+
dst: &mut String,
1564+
refs: Option<&mut HashSet<TsReference>>,
1565+
) {
15461566
match ty {
15471567
AdapterType::I32
15481568
| AdapterType::S8
@@ -1564,8 +1584,11 @@ fn adapter2ts(ty: &AdapterType, dst: &mut String, refs: Option<&mut HashSet<TsRe
15641584
AdapterType::Bool => dst.push_str("boolean"),
15651585
AdapterType::Vector(kind) => dst.push_str(&kind.js_ty()),
15661586
AdapterType::Option(ty) => {
1567-
adapter2ts(ty, dst, refs);
1568-
dst.push_str(" | undefined");
1587+
adapter2ts(ty, position, dst, refs);
1588+
dst.push_str(match position {
1589+
TypePosition::Argument => " | null | undefined",
1590+
TypePosition::Return => " | undefined",
1591+
});
15691592
}
15701593
AdapterType::NamedExternref(name) => dst.push_str(name),
15711594
AdapterType::Struct(name) => dst.push_str(name),

crates/cli/tests/reference/echo.d.ts

+36-36
Original file line numberDiff line numberDiff line change
@@ -36,42 +36,42 @@ export function echo_vec_uninit_i64(a: BigInt64Array): BigInt64Array;
3636
export function echo_vec_string(a: (string)[]): (string)[];
3737
export function echo_struct(a: Foo): Foo;
3838
export function echo_vec_struct(a: (Foo)[]): (Foo)[];
39-
export function echo_option_u8(a?: number): number | undefined;
40-
export function echo_option_i8(a?: number): number | undefined;
41-
export function echo_option_u16(a?: number): number | undefined;
42-
export function echo_option_i16(a?: number): number | undefined;
43-
export function echo_option_u32(a?: number): number | undefined;
44-
export function echo_option_i32(a?: number): number | undefined;
45-
export function echo_option_u64(a?: bigint): bigint | undefined;
46-
export function echo_option_i64(a?: bigint): bigint | undefined;
47-
export function echo_option_u128(a?: bigint): bigint | undefined;
48-
export function echo_option_i128(a?: bigint): bigint | undefined;
49-
export function echo_option_usize(a?: number): number | undefined;
50-
export function echo_option_isize(a?: number): number | undefined;
51-
export function echo_option_f32(a?: number): number | undefined;
52-
export function echo_option_f64(a?: number): number | undefined;
53-
export function echo_option_bool(a?: boolean): boolean | undefined;
54-
export function echo_option_char(a?: string): string | undefined;
55-
export function echo_option_string(a?: string): string | undefined;
56-
export function echo_option_vec_u8(a?: Uint8Array): Uint8Array | undefined;
57-
export function echo_option_vec_i8(a?: Int8Array): Int8Array | undefined;
58-
export function echo_option_vec_u16(a?: Uint16Array): Uint16Array | undefined;
59-
export function echo_option_vec_i16(a?: Int16Array): Int16Array | undefined;
60-
export function echo_option_vec_u32(a?: Uint32Array): Uint32Array | undefined;
61-
export function echo_option_vec_i32(a?: Int32Array): Int32Array | undefined;
62-
export function echo_option_vec_u64(a?: BigUint64Array): BigUint64Array | undefined;
63-
export function echo_option_vec_i64(a?: BigInt64Array): BigInt64Array | undefined;
64-
export function echo_option_vec_uninit_u8(a?: Uint8Array): Uint8Array | undefined;
65-
export function echo_option_vec_uninit_i8(a?: Int8Array): Int8Array | undefined;
66-
export function echo_option_vec_uninit_u16(a?: Uint16Array): Uint16Array | undefined;
67-
export function echo_option_vec_uninit_i16(a?: Int16Array): Int16Array | undefined;
68-
export function echo_option_vec_uninit_u32(a?: Uint32Array): Uint32Array | undefined;
69-
export function echo_option_vec_uninit_i32(a?: Int32Array): Int32Array | undefined;
70-
export function echo_option_vec_uninit_u64(a?: BigUint64Array): BigUint64Array | undefined;
71-
export function echo_option_vec_uninit_i64(a?: BigInt64Array): BigInt64Array | undefined;
72-
export function echo_option_vec_string(a?: (string)[]): (string)[] | undefined;
73-
export function echo_option_struct(a?: Foo): Foo | undefined;
74-
export function echo_option_vec_struct(a?: (Foo)[]): (Foo)[] | undefined;
39+
export function echo_option_u8(a?: number | null): number | undefined;
40+
export function echo_option_i8(a?: number | null): number | undefined;
41+
export function echo_option_u16(a?: number | null): number | undefined;
42+
export function echo_option_i16(a?: number | null): number | undefined;
43+
export function echo_option_u32(a?: number | null): number | undefined;
44+
export function echo_option_i32(a?: number | null): number | undefined;
45+
export function echo_option_u64(a?: bigint | null): bigint | undefined;
46+
export function echo_option_i64(a?: bigint | null): bigint | undefined;
47+
export function echo_option_u128(a?: bigint | null): bigint | undefined;
48+
export function echo_option_i128(a?: bigint | null): bigint | undefined;
49+
export function echo_option_usize(a?: number | null): number | undefined;
50+
export function echo_option_isize(a?: number | null): number | undefined;
51+
export function echo_option_f32(a?: number | null): number | undefined;
52+
export function echo_option_f64(a?: number | null): number | undefined;
53+
export function echo_option_bool(a?: boolean | null): boolean | undefined;
54+
export function echo_option_char(a?: string | null): string | undefined;
55+
export function echo_option_string(a?: string | null): string | undefined;
56+
export function echo_option_vec_u8(a?: Uint8Array | null): Uint8Array | undefined;
57+
export function echo_option_vec_i8(a?: Int8Array | null): Int8Array | undefined;
58+
export function echo_option_vec_u16(a?: Uint16Array | null): Uint16Array | undefined;
59+
export function echo_option_vec_i16(a?: Int16Array | null): Int16Array | undefined;
60+
export function echo_option_vec_u32(a?: Uint32Array | null): Uint32Array | undefined;
61+
export function echo_option_vec_i32(a?: Int32Array | null): Int32Array | undefined;
62+
export function echo_option_vec_u64(a?: BigUint64Array | null): BigUint64Array | undefined;
63+
export function echo_option_vec_i64(a?: BigInt64Array | null): BigInt64Array | undefined;
64+
export function echo_option_vec_uninit_u8(a?: Uint8Array | null): Uint8Array | undefined;
65+
export function echo_option_vec_uninit_i8(a?: Int8Array | null): Int8Array | undefined;
66+
export function echo_option_vec_uninit_u16(a?: Uint16Array | null): Uint16Array | undefined;
67+
export function echo_option_vec_uninit_i16(a?: Int16Array | null): Int16Array | undefined;
68+
export function echo_option_vec_uninit_u32(a?: Uint32Array | null): Uint32Array | undefined;
69+
export function echo_option_vec_uninit_i32(a?: Int32Array | null): Int32Array | undefined;
70+
export function echo_option_vec_uninit_u64(a?: BigUint64Array | null): BigUint64Array | undefined;
71+
export function echo_option_vec_uninit_i64(a?: BigInt64Array | null): BigInt64Array | undefined;
72+
export function echo_option_vec_string(a?: (string)[] | null): (string)[] | undefined;
73+
export function echo_option_struct(a?: Foo | null): Foo | undefined;
74+
export function echo_option_vec_struct(a?: (Foo)[] | null): (Foo)[] | undefined;
7575
export class Foo {
7676
private constructor();
7777
free(): void;

0 commit comments

Comments
 (0)