ts

Attribute Macro ts 

Source
#[ts]
Expand description

Generate TypeScript interface bindings from a Rust struct.

Each field of the struct will be included in a TypeScript interface definition with camelCase field names and the corresponding TypeScript types.

§Example

#[ts]
struct Token {
    symbol: String,
    /// @default 18
    decimals: Option<u8>,
    total_supply: BigInt,
}

#[wasm_bindgen]
pub fn handle_token(token: IToken) {
    // Access fields via JS bindings
    let symbol = token.symbol();
    let decimals = token.decimals().unwrap_or(18.into());
    let total_supply = token.total_supply();

    // Convert the JS binding into the Rust struct via `parse`
    let token = token.parse();

    // Convert the Rust struct into the JS binding via `Into` / `From`
    let token: Token = token.into();
}

Under the hood, this will generate a TypeScript interface with JS bindings:

interface IToken {
  symbol: string;
  /**
   * @default 18
   */
  decimals?: number | undefined;
  totalSupply: bigint;
}

§Nested Structs

To nest structs, the ts attribute must be applied to each struct individually. Then, the bindings can be used as fields in other structs.

#[ts]
struct Order {
    account: String,
    amount: BigInt,
    token: IToken, // Binding to the `Token` struct
}

§Arguments

The ts attribute accepts the following arguments when applied to a struct:

  • name: The name of the TypeScript interface and binding. Defaults to I{StructName}.
  • extends: A comma-separated list of interfaces to extend.
#[ts(name = JsToken)]
struct Token {
    symbol: String,
    decimals: Number,
    total_supply: BigInt,
}

#[ts(name = JsShareToken, extends = JsToken)]
struct ShareToken {
    price: BigInt,
}

#[wasm_bindgen]
pub fn handle_token(token: JsShareToken) {
    let symbol = token.symbol(); // Access base struct fields
}

This will generate the following TypeScript interfaces:

interface JsToken {
  // ...
}
interface JsShareToken extends JsToken {
  // ...
}

§Field Arguments

To customize the TypeScript interface, the ts attribute can be applied to individual fields of the struct. The attribute accepts the following arguments when applied to a field:

  • name: The name of the field in the TypeScript interface as a string. Defaults to the camelCase version of the Rust field name.
  • type: The TypeScript type of the field as a string. Defaults to best-effort inferred.
  • optional: Whether the field is optional in TypeScript. Defaults to inferred.
#[ts]
struct Params {
    #[ts(name = "specialCASING")]
    special_casing: String,

   #[ts(type = "`0x${string}`")]
   special_format: String,

    // The `Option` type is inferred as optional
    optional_field_and_value: Option<String>,

    #[ts(optional = false)]
    optional_value: Option<String>,

    // CAUTION: This will make the field optional in TypeScript, but Rust
    // will still expect a String, requiring manual runtime checks.
    #[ts(optional = true)]
    optional_field: String,
}

This will generate the following TypeScript interface:

interface IParams {
   specialCASING: string;
   specialFormat: `0x${string}`;
   optionalFieldAndValue?: string | undefined;
   optionalValue: string | undefined;
   optionalField?: string;
}