---
title: "Custom JS Types"
description: "JavaScript policies already receive the typed OpenPit SDK surface directly: Order, ExecutionReport, Context, PolicyReject, and the other callback types."
---

# Custom JS Types

JavaScript policies already receive the typed OpenPit SDK surface directly:
`Order`, `ExecutionReport`, `Context`, `PolicyReject`, and the other callback
types are regular JS/TS objects exposed by the binding. Intersect an SDK model
with application fields and use it as a `Policy` type parameter; callbacks then
receive a fresh clone of the submitted object with those fields preserved.

## When to Use

Use the plain JS policy interface when:

- you want a custom pre-trade or post-trade policy in JavaScript or TypeScript;
- you need project-specific fields next to the standard `Order` /
  `ExecutionReport` fields;
- you want callback typing directly from the package exports.

The standard fields remain validated by OpenPit. Host-specific fields stay
opaque to the engine and are available only to custom policy code.

## Building Blocks

Custom-type support uses the ordinary JS package surface:

<!-- markdownlint-disable MD013 -->
| Piece | Role |
| --- | --- |
| `Order` / `ExecutionReport` | Validated SDK models that application fields can intersect or extend. |
| `Policy<OrderModel, ExecutionReportModel>` | Keeps the application payload types visible in every applicable callback. |
| `Engine.builder().preTrade(policy)` | Registers the typed policy directly; no adapter or separate client engine is required. |
<!-- markdownlint-enable MD013 -->

Use an SDK wrapper when the application wants model methods and setters. A
plain object with the same standard groups is also accepted at the engine
boundary, but an intersection with `Order` or `ExecutionReport` is the most
direct way to type custom policy callbacks.

## Complete Example

The complete runnable example lives in
[Policy API - JS Custom Models](Policy-API.md#js-custom-models). Keeping the code
in the all-language policy reference gives the example one canonical source
while this page focuses on JavaScript- and TypeScript-specific guidance.

## Lifecycle / Payload Contract

- The application model must include the standard `Order` or `ExecutionReport`
  surface so the engine can validate it.
- `Policy<OrderModel, ExecutionReportModel>` keeps host fields typed in every
  applicable callback. The default model parameters remain `Order` and
  `ExecutionReport`.
- Each policy receives its own fresh clone, so one callback cannot mutate the
  object observed by a later policy.
- Cloning preserves application-owned string keys, symbol keys, prototypes,
  cycles, and shared references. Standard SDK fields are normalized and
  validated independently.
- Input payloads are borrowed for the duration of the call. Only lifecycle
  handles returned by the engine (`Request`, `Reservation`, and `Mutation`) are
  single-use and consumed by their terminal operation.

## Threading

The WebAssembly engine is single-threaded in JS, so a custom policy runs
synchronously on the caller's thread. There is no user-selectable sync mode or
off-thread callback execution. Use one engine per worker or isolate when the
application needs parallelism.

## Related Pages

- [Policy API](Policy-API.md): full callback contract and rollback patterns
- [Getting Started](Getting-Started.md): first engine construction and end-to-end flow
- [Policies](Policies.md): built-in controls and custom policy registration
- [Custom Go Types](Custom-Go-Types.md): typed Go client payloads
- [Custom Python Types](Custom-Python-Types.md): Python model subclasses
- [Custom Cpp Types](Custom-Cpp-Types.md): C++ polymorphic client payloads
- [Custom Rust Types](Custom-Rust-Types.md): Rust capability-trait composition
