docs

API Schemas and TypeScript

Export native API schemas to generate TypeScript declarations for page scripts.

On this page

You can export an API schema describing the functions, classes, and events exposed to JavaScript as JSON.

Generating TypeScript declarations from that schema gives editors autocomplete and type checking for calls made from the page.

Getting the Schema

Call schema() to read the schema as a JSON string, or DumpSchema() to write it directly to a file:

C++
std::string json = api.schema();
api.DumpSchema("myapp-schema.json");

The schema describes parameter and return types for every binding, named structs and enums, and declared events, along with any documentation and metadata added by native code.

Naming Parameters and Adding Documentation

Pass js::Param and js::Doc after the callable to add parameter names and documentation to a binding:

C++
api.Bind("add", [](double a, double b) { return a + b; },
         js::Param("a"), js::Param("b"), js::Doc("Adds two numbers."));

Explicit calls like Bind(), DefineEvent(), and class methods accept these arguments. The property assignment form (api["add"] = ...) takes no annotations.

Annotation Rules

You must provide a name for every parameter or leave them all unnamed. Naming only some of the parameters causes a compile error.

Parameter names appear in generated declarations, the schema, and runtime TypeError messages. Unnamed parameters fall back to arg0 and arg1.

Documentation strings from js::Doc populate the doc field in the schema and show as hover descriptions in editors. For function binding basics, see Extending JavaScript with Native API.

Adding Metadata

Call SetMetadata() to merge a JSON object into the schema entry at a specific path:

C++
api.SetMetadata("", R"({"meta": {"version": "2.1.0"}})");

Passing an empty string for the path targets the schema root, which holds top-level sections like meta, events, and types.

Objects merge field by field, and values from later calls replace earlier ones.

🚧 Rebinding Clears Metadata

Rebinding an existing path removes its metadata. Always call SetMetadata() after the Bind() call it describes.

Generating TypeScript Declarations

Scripts on the page call native functions without compile-time checks— any misspelled identifier or invalid argument triggers a TypeError only at runtime.

The gen-typescript.py tool in tools/scripts/ converts an exported schema file into a .d.ts declaration file. Adding this file to a web project gives editors autocomplete, type checking, and hover documentation, even in plain JavaScript projects.

Generation Steps

Generate the declaration file in three steps:

  1. Export the schema file from a debug build:
C++
#ifndef NDEBUG
api.DumpSchema("myapp-schema.json");
#endif
  1. Run the script to produce the declaration file:
Shell
python tools/scripts/gen-typescript.py myapp-schema.json -o myApp.d.ts

For the earlier add() binding, the script generates this declaration:

TypeScript
declare namespace myApp {
  /** Adds two numbers. */
  function add(a: number, b: number): number;
}
  1. Add the .d.ts file to the web project.

Checking Plain JavaScript

You can take advantage of the declarations in plain JavaScript without setting up a TypeScript build.

Add a jsconfig.json file beside the web files to enable type checking across the project:

JSON
{
  "compilerOptions": { "checkJs": true },
  "include": ["**/*.js", "myApp.d.ts"]
}

To check a single file instead, add /// <reference path="myApp.d.ts" /> and // @ts-check to the top of that file.

The editor flags invalid arguments and misspelled names while typing:

JavaScript
myApp.add(1, "2");
// Argument of type 'string' is not assignable to parameter of type 'number'.
myApp.ad(1, 2);
// Property 'ad' does not exist on type 'typeof myApp'.

Recommended Practices