Expand description
§Tsify
Tsify is a library for generating TypeScript definitions from Rust code.
Using this with wasm-bindgen will automatically output the types to .d.ts.
Inspired by typescript-definitions and ts-rs.
§Example
Click to show Cargo.toml.
[dependencies]
tsify = "0.5.7"
serde = { version = "1.0", features = ["derive"] }
wasm-bindgen = { version = "0.2" }use serde::{Deserialize, Serialize};
use tsify::Tsify;
use tsify::Ts;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsError;
#[derive(Tsify, Serialize, Deserialize)]
pub struct Point {
x: i32,
y: i32,
}
#[wasm_bindgen]
pub fn into_js() -> Result<Ts<Point>, JsError> {
let point = Point { x: 0, y: 0 };
Ok(point.into_ts()?)
}
#[wasm_bindgen]
pub fn from_js(point: Ts<Point>) -> Result<(), JsError> {
let point: Point = point.to_rust()?;
Ok(())
}Will generate the following .d.ts file:
/* tslint:disable */
/* eslint-disable */
export interface Point {
x: number;
y: number;
}
export function from_js(point: Point): void;
export function into_js(): Point;This is the behavior due to typescript_custom_section and Rust Type conversions.
§Crate Features
json(default) enables serialization throughserde_json.jsenables serialization throughserde-wasm-bindgenand generates the appropriate types for it. This will be the default in future versions.
§Attributes
Tsify container attributes
into_wasm_abi(deprecated) implementsIntoWasmAbiandOptionIntoWasmAbi. This can be converted directly from Rust to JS viaserde_jsonorserde-wasm-bindgen. Deprecated in favour of usingTs<T>as on function parameters and return type (why).from_wasm_abi(deprecated) implementsFromWasmAbiandOptionFromWasmAbi. This is the opposite operation of the above. Deprecated in favour of usingTs<T>as on function parameters and return type (why).namespacegenerates a namespace for the enum variants.typeoverrides at the container level.type_paramsoverrides params at the container level.
Serializer configuration options
missing_as_nullhashmap_as_objectlarge_number_types_as_bigints
Tsify field attributes
typetype_paramsoptional
Serde attributes
renamerename-alltagcontentuntaggedskipskip_serializingskip_deserializingskip_serializing_if = "Option::is_none"flattendefaulttransparent
§Why are the wasm_abi attributes deprecated?
#[tsify(into_wasm_abi, from_wasm_abi)] moves (de)serialization into the wasm-bindgen ABI boundary, and that boundary cannot report failure.
wasm_bindgen::convert::FromWasmAbi::from_abi returns Self, not Result<Self, _>, and there is no fallible variant of it or of RefFromWasmAbi / LongRefFromWasmAbi / VectorFromWasmAbi. So when serde fails to deserialize what JavaScript passed in, the generated impl has only one way out: wasm_bindgen::throw_str, which raises a JavaScript exception that unwinds straight past the wasm frames. As wasm-bindgen’s own documentation warns:
Note that it is very easy to leak memory with this function because this function, unlike
panic!on other platforms, will not run destructors.
Everything alive at that moment leaks: the serde error, the partially deserialized value, and — because arguments are converted one after another — every argument already converted before the failing one. From JavaScript this looks like an ordinary, catchable exception, so an application can appear to handle bad input correctly while its wasm heap grows on every failure, until the instance dies with RuntimeError: memory access out of bounds (see #65 and #86).
Ts<T> keeps the boundary infallible: it is a #[repr(transparent)] wrapper whose FromWasmAbi impl only forwards the underlying JsValue. Deserialization then happens inside your function, where it is an ordinary Result — the from_js example at the top of this page shows the shape. Because the function returns normally, destructors run and nothing leaks. The generated TypeScript is unchanged, so .d.ts consumers are unaffected.
Ts<T> needs only #[derive(Tsify)] — do not add #[tsify(from_wasm_abi)] alongside it. Note also that Ts<Vec<T>> is not supported, only Vec<Ts<T>>; to convert a whole vector, use items.into_iter().map(|x| x.to_rust()).collect::<Result<Vec<_>, _>>()?.
§Type Override
use tsify::Tsify;
#[derive(Tsify)]
pub struct Foo {
#[tsify(type = "0 | 1 | 2")]
x: i32,
}Generated type:
export interface Foo {
x: 0 | 1 | 2;
}§Optional Properties
use tsify::Tsify;
#[derive(Tsify)]
struct Optional {
#[tsify(optional)]
a: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
b: Option<String>,
#[serde(default)]
c: i32,
}Generated type:
export interface Optional {
a?: number;
b?: string;
c?: number;
}§Enum
use tsify::Tsify;
#[derive(Tsify)]
enum Color {
Red,
Blue,
Green,
Rgb(u8, u8, u8),
Hsv {
hue: f64,
saturation: f64,
value: f64,
},
}Generated type:
export type Color =
| "Red"
| "Blue"
| "Green"
| { Rgb: [number, number, number] }
| { Hsv: { hue: number; saturation: number; value: number } };§Enum with namespace
use tsify::Tsify;
#[derive(Tsify)]
#[tsify(namespace)]
enum Color {
Red,
Blue,
Green,
Rgb(u8, u8, u8),
Hsv {
hue: f64,
saturation: f64,
value: f64,
},
}Generated type:
declare namespace Color {
export type Red = "Red";
export type Blue = "Blue";
export type Green = "Green";
export type Rgb = { Rgb: [number, number, number] };
export type Hsv = {
Hsv: { hue: number; saturation: number; value: number };
};
}
export type Color = Color.Red | Color.Blue | Color.Green | Color.Rgb | Color.Hsv;§Type Aliases
use tsify::{declare, Tsify};
#[derive(Tsify)]
struct Foo<T>(T);
#[declare]
type Bar = Foo<i32>;Generated type:
export type Foo<T> = T;
export type Bar = Foo<number>;Structs§
- Error
- An error type wrapping serialization or deserialization errors from either
serde_jsonorserde_wasm_bindgen, depending on whether thejsonorjsfeature is enabled. - Serialization
Config - Ts
- A wrapper for a type implementing
Tsify, to be used in#[wasm_bindgen]function parameters and return types.
Traits§
- JsValue
Serde Ext - Extension trait to provide conversion between
JsValueandserde. - Tsify
Tsifyis a trait that allows you to convert a type to and from JavaScript. Can be implemented manually if you need to customize the serialization or deserialization.
Attribute Macros§
- declare
- The
declaremacro, used in#[declare]annotations.
Derive Macros§
- Tsify
- The
Tsifyderive macro, used in#[derive(Tsify, ...)]annotations.