js-sys
The js-sys crate provides bindings to all JavaScript global APIs guaranteed to exist in every JavaScript environment by the ECMAScript standard.
Wasm-bindgen supports generic typing using type erasure for imported JavaScript types. Generic parameters exist only in Rust code—they are completely erased in the generated JavaScript bindings.
For a conceptual overview and usage guide, see Working with Generics.
When passing a typed value (e.g.,
Array<Number>) to a function expecting a wider type (e.g.,&Array<JsValue>), use theupcast()method:my_array.upcast(). See Upcasting Types for details.
All generic types listed implement JsGeneric and default to JsValue when type parameters are unspecified.
| Type | Description |
|---|---|
Array<T> | Typed JavaScript array |
ArrayTuple<T1, ..., T8> | Array with per-item typing (up to 8) |
Function<fn(A) -> R> | Typed function with return and arguments |
Promise<T> | Promise resolving to T |
Map<K, V> | Typed map |
Set<T> | Typed set |
Iterator<T> / AsyncIterator<T> | Typed iterators |
Generator<T> / AsyncGenerator<T> | Typed generators |
Object<T> | Object with typed values |
WeakMap<K, V> / WeakSet<T> / WeakRef<T> | Weak collections |
JsOption<T> | Nullable JS value (T, null, or undefined) |
Number | JavaScript number primitive |
JsString | JavaScript string primitive |
Boolean | JavaScript boolean primitive |
BigInt | JavaScript BigInt primitive |
Symbol | JavaScript Symbol primitive |
Undefined | JavaScript undefined value |
Null | JavaScript null value |
Array<T>
Typed JavaScript Array builtin.
#![allow(unused)]
fn main() {
use js_sys::{Array, Number, JsString};
let numbers: Array<Number> = Array::new_typed();
numbers.push(&Number::from(42));
let first: Number = numbers.get(0);
for num in numbers.iter() {
// num is Number
}
}
ArrayTuple<T1, …, T8>
JavaScript Array with per-item typing, supporting up to 8 items.
#![allow(unused)]
fn main() {
use js_sys::{ArrayTuple, Number, JsString, Boolean};
let tuple: ArrayTuple<Number, JsString, Boolean> = ArrayTuple::new();
tuple.set0(&Number::from(1));
tuple.set1(&JsString::from("hello"));
tuple.set2(&Boolean::from(true));
let n: Number = tuple.get0();
let s: JsString = tuple.get1();
let b: Boolean = tuple.get2();
}
Function<fn(A) -> R>
Typed JavaScript function with return type and up to 8 arguments.
#![allow(unused)]
fn main() {
use js_sys::{Function, Number, JsString};
#[wasm_bindgen]
extern "C" {
fn getFormatter() -> Function<fn(Number) -> JsString>;
}
let formatter = getFormatter();
let result: JsString = formatter.call1(&JsValue::UNDEFINED, &Number::from(42))?;
}
Type aliases
| Alias | Description |
|---|---|
TypedFunction | Strict arity checking (arguments default to None) |
AnyFunction | Lenient behavior (arguments default to JsValue) |
VoidFunction | Function<fn(...) -> Undefined> with strict arity |
Calling with tuples
#![allow(unused)]
fn main() {
let f: Function<fn(JsString, Boolean) -> Number> = get_function();
// call accepts a tuple of references
let result = f.call(&context, ())?; // no args
let result = f.call(&context, (&my_string,))?; // one arg
let result = f.call(&context, (&my_string, &my_bool))?; // two args
// bindn returns a new function with arguments pre-bound
let bound: Function<fn(Boolean) -> Number> = f.bindn(&context, (&my_string,));
// Argument upcasting: pass subtypes where supertypes are expected
let f: Function<fn(JsValue, JsValue) -> Number> = get_function();
let result = f.call(&context, (&my_number, &my_string))?; // Number, JsString upcast to JsValue
}
Converting from Closures
Use Function::from_closure() to convert owned Closure types to typed Function, and Function::closure_ref() for borrowed closures:
#![allow(unused)]
fn main() {
use js_sys::{Function, Number, JsString};
use wasm_bindgen::prelude::*;
// Owned closure to Function (transfers ownership to JS)
let closure: Closure<dyn FnMut(Number) -> JsString> = Closure::new(|n: Number| {
JsString::from(format!("Value: {}", n.value_of()))
});
let func: Function<fn(Number) -> JsString> = Function::from_closure(closure);
}
For borrowed closures, use closure_ref:
#![allow(unused)]
fn main() {
let mut count = 0u32;
let mut increment = || {
count += 1;
Number::from(count)
};
let closure = ScopedClosure::borrow_mut(&mut increment);
let func: &Function<fn() -> Number> = Function::closure_ref(&closure);
}
Primitive type coercion
Rust primitives automatically coerce to JS types in closure return positions:
#![allow(unused)]
fn main() {
// u32 coerces to Number
let closure: Closure<dyn Fn() -> u32> = Closure::new(|| 42);
let func: Function<fn() -> Number> = Function::from_closure(closure);
// String coerces to JsString
let closure: Closure<dyn Fn() -> String> = Closure::new(|| "hello".to_string());
let func: Function<fn() -> JsString> = Function::from_closure(closure);
}
This works for all numeric primitives (u8, i32, f64, etc.) and string types (String, &str, char).
See Passing Rust Closures to JS for more details on closure types and lifecycle management.
Promise<T>
Typed JavaScript Promise that resolves to T.
#![allow(unused)]
fn main() {
use js_sys::{Promise, Number};
#[wasm_bindgen]
extern "C" {
fn fetchCount() -> Promise<Number>;
}
let count: Number = JsFuture::from(fetchCount()).await?;
}
The Promising trait
The Promising trait represents types that are either T or Promise<T>. Use it to accept both immediate values and promises in function signatures:
#![allow(unused)]
fn main() {
use js_sys::{Promising, Promise, Number};
#[wasm_bindgen]
extern "C" {
// Accepts either Number or Promise<Number>
fn getValue<T: Promising<Resolution = Number>>(value: T) -> Promise<Number>;
}
}
Map<K, V>
Typed JavaScript Map builtin.
#![allow(unused)]
fn main() {
use js_sys::{Map, JsString, Number};
let map: Map<JsString, Number> = Map::new_typed();
map.set(&JsString::from("key"), &Number::from(100));
let value: Number = map.get(&JsString::from("key"));
}
Set<T>
Typed JavaScript Set builtin.
#![allow(unused)]
fn main() {
use js_sys::{Set, JsString};
let set: Set<JsString> = Set::new_typed();
set.add(&JsString::from("value"));
let has: bool = set.has(&JsString::from("value"));
}
Iterator<T> and AsyncIterator<T>
Typed iterators for synchronous and asynchronous iteration.
#![allow(unused)]
fn main() {
use js_sys::{Iterator, Number};
#[wasm_bindgen]
extern "C" {
fn getNumberIterator() -> Iterator<Number>;
}
let iter = getNumberIterator();
while let Some(num) = iter.next() {
// num is Number
}
}
The Iterable and AsyncIterable traits
The Iterable and AsyncIterable traits represent objects implementing the iterator protocol via [Symbol.iterator]() or [Symbol.asyncIterator](). Use them to accept any iterable type in function signatures:
#![allow(unused)]
fn main() {
use js_sys::{Iterable, AsyncIterable, Number};
#[wasm_bindgen]
extern "C" {
// Accepts Array, Set, Generator, or any other iterable
fn processIterable<T: Iterable<Item = Number>>(items: T);
// Accepts AsyncGenerator or any other async iterable
fn processAsyncIterable<T: AsyncIterable<Item = Number>>(items: T);
}
}
Generator<T> and AsyncGenerator<T>
Typed generator builtins.
#![allow(unused)]
fn main() {
use js_sys::{Generator, Number};
#[wasm_bindgen]
extern "C" {
fn createGenerator() -> Generator<Number>;
}
let gen = createGenerator();
let result = gen.next();
}
Object<T>
Typed object records where values are of type T.
#![allow(unused)]
fn main() {
use js_sys::{Object, Number};
let obj: Object<Number> = Object::new_typed();
}
WeakMap<K, V>, WeakSet<T>, WeakRef<T>
Typed weak collection builtins.
#![allow(unused)]
fn main() {
use js_sys::{WeakMap, WeakSet, WeakRef, Object, Number};
let weak_map: WeakMap<Object, Number> = WeakMap::new_typed();
let weak_set: WeakSet<Object> = WeakSet::new_typed();
let weak_ref: WeakRef<Object> = WeakRef::new(&my_object);
}
JsOption<T>
Represents a JS value that may be T, null, or undefined.
#![allow(unused)]
fn main() {
use wasm_bindgen::JsOption;
use js_sys::Number;
#[wasm_bindgen]
extern "C" {
fn maybeGetValue() -> JsOption<Number>;
}
let value = maybeGetValue();
// Check emptiness
if value.is_empty() {
// null or undefined
}
// Convert to Option
match value.into_option() {
Some(num) => { /* use num */ }
None => { /* handle null */ }
}
// Unwrap methods
let num = value.unwrap();
let num = value.expect("should exist");
let num = value.unwrap_or_default();
let num = value.unwrap_or_else(|| Number::from(0));
// Create values
let with_value = JsOption::wrap(Number::from(42));
let empty: JsOption<Number> = JsOption::new();
let from_opt = JsOption::from_option(Some(Number::from(42)));
}
JsOption<T> vs Option<T>:
| Type | Behavior |
|---|---|
Option<T> | Undefined or Null check at ABI boundary, immediately converts to Some(T) or None |
JsOption<T> | Defers undefined or null check, works in JsGeneric positions |