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

# Generate flag types

> Generate TypeScript flag types or Go accessors and variant constants.

## Overview

The CLI generates TypeScript types or Go accessors from the local flag config. TypeScript output defaults to `src/generated/flags.ts`. Pass its `FlagDefinitions` type to the SDK and flag keys, variant names, and value types are checked at compile time. A misspelled key fails the build instead of silently serving a default.

## Generated output

```ts TypeScript theme={null}
// src/generated/flags.ts
/* eslint-disable */
/* This file is generated by shipd types gen. Do not edit. */

export interface FlagDefinitions {
  "new-checkout": {
    type: "boolean";
    default: false;
  };

  "search-variant": {
    type: "variant";
    variants: "control" | "semantic" | "hybrid";
    default: "control";
  };

  "max-retries": {
    type: "number";
    default: 3;
  };

  "checkout-payload": {
    type: "json";
    default: {"mode":"strict","showPromo":true};
  };
}

export type FlagKey = keyof FlagDefinitions;

export type BooleanFlagKey = {
  [K in FlagKey]: FlagDefinitions[K]["type"] extends "boolean" ? K : never;
}[FlagKey];

export type VariantFlagKey = {
  [K in FlagKey]: FlagDefinitions[K]["type"] extends "variant" ? K : never;
}[FlagKey];

export type NumberFlagKey = {
  [K in FlagKey]: FlagDefinitions[K]["type"] extends "number" ? K : never;
}[FlagKey];

export type JsonFlagKey = {
  [K in FlagKey]: FlagDefinitions[K]["type"] extends "json" ? K : never;
}[FlagKey];
```

```go Go theme={null}
// internal/flags/flags_gen.go
// Code generated by shipd types gen --language go; DO NOT EDIT.
package flags

import (
	"encoding/json"
	shipd "github.com/alasti-company/useshipd.com/sdks/go"
)

// Defaults returns a fresh map of the config's defaults for shipd.Options.
func Defaults() map[string]any {
	var defaults map[string]any
	_ = json.Unmarshal([]byte("{\"checkout-payload\":{\"mode\":\"strict\",\"showPromo\":true},\"max-retries\":3,\"new-checkout\":false,\"search-variant\":\"control\"}"), &defaults)
	return defaults
}

const CheckoutPayloadKey = "checkout-payload"

func CheckoutPayload(client *shipd.Client, context shipd.EvaluationContext) any {
	return client.GetJSON(CheckoutPayloadKey, context)
}

const MaxRetriesKey = "max-retries"

func MaxRetries(client *shipd.Client, context shipd.EvaluationContext) float64 {
	return client.GetNumber(MaxRetriesKey, context)
}

const NewCheckoutKey = "new-checkout"

func NewCheckout(client *shipd.Client, context shipd.EvaluationContext) bool {
	return client.IsEnabled(NewCheckoutKey, context)
}

const SearchVariantKey = "search-variant"

type SearchVariantVariant string

const SearchVariantControl SearchVariantVariant = "control"

const SearchVariantSemantic SearchVariantVariant = "semantic"

const SearchVariantHybrid SearchVariantVariant = "hybrid"

func SearchVariant(client *shipd.Client, context shipd.EvaluationContext) SearchVariantVariant {
	return SearchVariantVariant(client.GetVariant(SearchVariantKey, context))
}
```

The exact shape is in [Generated types](/reference/config#generated-types).

## When it is written

| Command | Writes types |
| - | - |
| `shipd push` | After a successful apply. Not when there is nothing to push. |
| `shipd pull` | Always, after rewriting the selected flag config. |
| `shipd types gen` | Always. Reads only the local file; no network or credential needed. |

Types always come from the local flag config, never from the server. To write somewhere else, set `typesOut` in [`.shipd/config.json`](/reference/config#project-settings-file):

```json TypeScript theme={null}
{ "typesOut": "src/lib/shipd-flags.ts" }
```

```json Go theme={null}
{ "typesLanguage": "go", "typesOut": "internal/flags/flags_gen.go", "typesPackage": "flags" }
```

## Commit it

Commit `src/generated/flags.ts` alongside `shipd.config.ts`. Your app then type-checks on a fresh clone and in CI without running the CLI first, and pull requests show type changes next to flag changes.

* Never edit it by hand. The next push, pull, or `shipd types gen` overwrites it.
* If it drifts from `shipd.config.ts`, run `shipd types gen` and commit the result.
* To catch drift in CI, run `shipd types gen` and fail on `git diff --exit-code src/generated/flags.ts`.

## Use generated output with the SDK

Pass `FlagDefinitions` as the TypeScript client type argument, or import your module's generated Go `flags` package.

```ts TypeScript theme={null}
// src/flags.ts
import { createClient } from "shipdit";
import type { FlagDefinitions } from "./generated/flags";

export const shipd = createClient<FlagDefinitions>({
  sdkKey: process.env.SHIPD_SDK_KEY!,
  defaults: { "new-checkout": false, "search-variant": "control" },
});
```

```go Go theme={null}
// Import your module's internal/flags package as flags.
client, err := shipd.New(shipd.Options{
    SDKKey: os.Getenv("SHIPD_SDK_KEY"), Defaults: flags.Defaults(),
})
if err != nil { return err }
defer func() {
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    if err := client.Shutdown(ctx); err != nil { log.Printf("shipd events: %v", err) }
}()
user := shipd.EvaluationContext{UserID: "usr_8f2k19"}
if flags.NewCheckout(client, user) {
    // Serve the new checkout.
}
if flags.SearchVariant(client, user) == flags.SearchVariantSemantic {
    // Use semantic search.
}
retries := flags.MaxRetries(client, user) // float64
payload := flags.CheckoutPayload(client, user) // any; validate its shape
_ = retries
_ = payload
```

For React, create the typed bindings once:

```ts src/flags.ts (React) theme={null}
"use client";

import { createShipdReact } from "shipdit/client/react";
import type { FlagDefinitions } from "./generated/flags";

export const { ShipdProvider, useFlag, useVariant } = createShipdReact<FlagDefinitions>();
```

Without the type argument, any string is accepted as a key.

## Go output

```bash theme={null}
shipd types gen --language go --package flags --out internal/flags/flags_gen.go
```

Set `typesLanguage: "go"` and `typesPackage: "flags"` in [project settings](/reference/config#project-settings-file) to generate Go after push and pull too. Go output defaults to `internal/flags/flags_gen.go`.

The Go output above uses the four flags from the [Go tutorial](/examples/go). The generator creates one accessor per flag, its key constant, a `Defaults()` function, and named string types and constants for variants.

Misspelled accessor names and incompatible return types fail compilation. Go variant types are named strings, so Go still permits explicit conversions from arbitrary strings; they are not closed unions. JSON stays `any` because the served payload can change shape.

Flag keys become exported Go names (`new-checkout` → `NewCheckout`). Identifier collisions such as `new-checkout` and `new_checkout`, including collisions with generated variant constants, fail generation with a validation error. Rename the conflicting flag or variant.

Commit `internal/flags/flags_gen.go` alongside the config. Check drift with:

```bash theme={null}
shipd types gen --language go
git diff --exit-code internal/flags/flags_gen.go
```

## What a mistake looks like

```ts TypeScript theme={null}
// src/checkout.ts
if (shipd.isEnabled("new-chekout")) {
  // ...
}
```

```go Go theme={null}
// checkout.go
if flags.NewChekout(client, shipd.EvaluationContext{}) {
    // ...
}
// Compile error: undefined: flags.NewChekout
```

```text Output theme={null}
src/checkout.ts:1:21 - error TS2345: Argument of type '"new-chekout"' is not assignable to parameter of type '"new-checkout"'.
```

The same check catches reading a flag with the wrong method (`shipd.isEnabled("search-variant")`) and comparing against a variant that does not exist (`shipd.getVariant("search-variant") === "v3"`).

## Next steps

* [Sync flags in CI](/config-as-code/ci)
* [Node SDK](/sdks/node) · [Go SDK](/sdks/go) · [React](/sdks/react)
* [SDK reference](/reference/sdk)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.