> ## Documentation Index
> Fetch the complete documentation index at: https://forst-lang.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Generate client types

> Emit .d.ts from Forst with forst generate so Node clients match server shapes.

**`forst generate`** emits TypeScript declarations from the same definitions the compiler validates, so Node clients import shapes that match the server.

To call these functions at runtime, see [Call Forst from Node](/docs/interop/node/call-forst). To call legacy JavaScript from compiled Forst, see [Call JavaScript from Forst](/docs/interop/node/call-javascript).

## Manual types in TypeScript

Without generated types, every API change means updating TS by hand:

```typescript theme={"languages":{"custom":["/languages/forst.json"]}}
interface PlaceOrderInput {
  stockKeepingUnit: string; // any string
  quantity: number;         // any number
}
```

TypeScript cannot express `quantity` must be 1 to 99 unless you add Zod, Effect.Schema, or similar. That is another schema to maintain.

## Types from .ft

Define the shape once in Forst:

<Tabs>
  <Tab title="Forst">
    ```ft theme={"languages":{"custom":["/languages/forst.json"]}}
    type PlaceOrderInput = {
    	stockKeepingUnit: String.Min(1).Max(64),
    	quantity:         Int.Min(1).Max(99),
    }

    func placeOrder(in: PlaceOrderInput) {
    	// in is already validated; business logic starts here
    }
    ```
  </Tab>

  <Tab title="Generated Go">
    ```go theme={"languages":{"custom":["/languages/forst.json"]}}
    // forst build
    type PlaceOrderInput struct {
    	stockKeepingUnit string
    	quantity         int
    }

    func placeOrder(in PlaceOrderInput) {
    	if len(in.stockKeepingUnit) < 1 || len(in.stockKeepingUnit) > 64 { ... }
    	if in.quantity < 1 || in.quantity > 99 { ... }
    	// business logic starts here
    }
    ```
  </Tab>

  <Tab title="Generated TypeScript">
    ```typescript theme={"languages":{"custom":["/languages/forst.json"]}}
    // forst generate → generated/types.d.ts
    export interface PlaceOrderInput {
      quantity: number;
      stockKeepingUnit: string;
    }
    ```
  </Tab>
</Tabs>

Run:

```bash theme={"languages":{"custom":["/languages/forst.json"]}}
npx forst generate ./path/to/project
```

Output layout (typical):

```text theme={"languages":{"custom":["/languages/forst.json"]}}
generated/
├── types.d.ts      # merged type declarations
└── ...
client/             # optional client stubs (see Call Forst from Node)
```

Import in your frontend or BFF:

```typescript theme={"languages":{"custom":["/languages/forst.json"]}}
import type { PlaceOrderInput } from "./generated/types";

async function submitOrder(input: PlaceOrderInput) {
  // structural match with server-side Forst types
}
```

## Discovery with `ftconfig.json`

`forst generate` and `forst dev` share **include/exclude** rules from `ftconfig.json`:

```json theme={"languages":{"custom":["/languages/forst.json"]}}
{
  "files": {
    "include": ["**/*.ft"],
    "exclude": [
      "**/node_modules/**",
      "**/.git/**",
      "**/client/**"
    ]
  }
}
```

Pass **`-config`** explicitly or let the CLI search upward from your target directory.

## End-to-end example

The **tictactoe** example in the repository demonstrates merged-package generate:

```bash theme={"languages":{"custom":["/languages/forst.json"]}}
task example:tictactoe:generate
```

See [`examples/in/tictactoe/`](https://github.com/forst-lang/forst/tree/main/examples/in/tictactoe) and [`examples/client-integration/`](https://github.com/forst-lang/forst/tree/main/examples/client-integration).

## Caveats

### Structure only in TypeScript

Generated **`.d.ts`** files reflect field names and types. They do **not** carry runtime rules like **`String.Min(1)`** or **`Int.Max(99)`**. Add client validation yourself, or call the Forst server which validates at the boundary.

### Provider gated exports

Functions that need wired **`Providers(f)`** are excluded from TypeScript emit. The invoke wire stays payload only. See [Providers § Caveats](/docs/language/providers#caveats).

### Nominal error tags

TypeScript **`_tag`** export for nominal errors is still maturing. Treat error payloads as evolving. See [Errors and Result § Caveats](/docs/language/errors-and-result#caveats).

## Related

<CardGroup cols={2}>
  <Card title="Call Forst from Node" icon="https://mintcdn.com/forst/r5GJChnfkgCSJa-b/icons/typescript.svg?fit=max&auto=format&n=r5GJChnfkgCSJa-b&q=85&s=8a8c0cd7b4bf60c264d51f66d0f52e91" href="/docs/interop/node/call-forst" width="512" height="512" data-path="icons/typescript.svg">
    Invoke generated functions — dev server or built-in HTTP server.
  </Card>

  <Card title="Call JavaScript from Forst" icon="https://mintcdn.com/forst/r5GJChnfkgCSJa-b/icons/typescript.svg?fit=max&auto=format&n=r5GJChnfkgCSJa-b&q=85&s=8a8c0cd7b4bf60c264d51f66d0f52e91" href="/docs/interop/node/call-javascript" width="512" height="512" data-path="icons/typescript.svg">
    Call legacy `.ts`/`.js` from compiled Forst (`import node`).
  </Card>

  <Card title="Node overview" icon="server" href="/docs/interop/node">
    Pick your migration path.
  </Card>

  <Card title="Installation" icon="download" href="/docs/installation">
    Install `@forst/cli` in your project.
  </Card>
</CardGroup>
