# Feature Flag

> Feature flag with variants, targeting rules, and evaluation result.

- Name: `feature-flag`
- Categories: infrastructure
- Detail page: https://open-types.dev/types/feature-flag

## Install

```bash
# Types only
npx shadcn add @open-types/feature-flag

# Types + Zod v4 validators
npx shadcn add @open-types/feature-flag-zod

# Types + real-world examples
npx shadcn add @open-types/feature-flag-examples
```

## Types

```typescript
export type FeatureFlagOperator =
  | "eq"
  | "neq"
  | "in"
  | "nin"
  | "gt"
  | "lt"
  | "gte"
  | "lte"
  | "contains";

export interface FeatureFlagRule {
  attribute: string;
  operator: FeatureFlagOperator;
  value: unknown;
}

export interface FeatureFlagVariant {
  key: string;
  value: unknown;
  weight?: number;
}

export interface FeatureFlag {
  key: string;
  enabled: boolean;
  description?: string;
  variants?: FeatureFlagVariant[];
  rules?: FeatureFlagRule[];
}

export interface FeatureFlagEvaluation {
  key: string;
  enabled: boolean;
  variant?: string;
  reason?: string;
}
```

## Zod validator

```typescript
import * as z from "zod";
import type {
  FeatureFlag,
  FeatureFlagEvaluation,
  FeatureFlagOperator,
  FeatureFlagRule,
  FeatureFlagVariant,
} from "../types/feature-flag";

export const featureFlagOperatorSchema = z.enum([
  "eq",
  "neq",
  "in",
  "nin",
  "gt",
  "lt",
  "gte",
  "lte",
  "contains",
]) satisfies z.ZodType<FeatureFlagOperator>;

export const featureFlagRuleSchema = z.object({
  attribute: z.string().min(1, { error: "Attribute is required" }),
  operator: featureFlagOperatorSchema,
  value: z.unknown(),
}) satisfies z.ZodType<FeatureFlagRule>;

export const featureFlagVariantSchema = z.object({
  key: z.string().min(1, { error: "Variant key is required" }),
  value: z.unknown(),
  weight: z.number().min(0, { error: "Weight must be greater than or equal to 0" }).optional(),
}) satisfies z.ZodType<FeatureFlagVariant>;

export const featureFlagSchema = z.object({
  key: z.string().min(1, { error: "Feature flag key is required" }),
  enabled: z.boolean(),
  description: z.string().optional(),
  variants: z.array(featureFlagVariantSchema).optional(),
  rules: z.array(featureFlagRuleSchema).optional(),
}) satisfies z.ZodType<FeatureFlag>;

export const featureFlagEvaluationSchema = z.object({
  key: z.string().min(1, { error: "Feature flag key is required" }),
  enabled: z.boolean(),
  variant: z.string().optional(),
  reason: z.string().optional(),
}) satisfies z.ZodType<FeatureFlagEvaluation>;

export type {
  FeatureFlag,
  FeatureFlagEvaluation,
  FeatureFlagOperator,
  FeatureFlagRule,
  FeatureFlagVariant,
} from "../types/feature-flag";
```

## Examples

```typescript
// Source: hand-crafted; modeled after LaunchDarkly/GrowthBook/Unleash payloads
import type {
  FeatureFlagOperator,
  FeatureFlagRule,
  FeatureFlagVariant,
  FeatureFlag,
  FeatureFlagEvaluation,
} from "../types/feature-flag";

export const featureFlagOperatorExamples = {
  eq: "eq",
  neq: "neq",
  in: "in",
  nin: "nin",
  gt: "gt",
  lt: "lt",
  gte: "gte",
  lte: "lte",
  contains: "contains",
} as const satisfies Record<string, FeatureFlagOperator>;

const ruleOrgIn = {
  attribute: "org_id",
  operator: "in",
  value: ["org_001", "org_002"],
} as const satisfies FeatureFlagRule;

const ruleEmailDomain = {
  attribute: "email",
  operator: "contains",
  value: "@example.com",
} as const satisfies FeatureFlagRule;

export const featureFlagRuleExamples = {
  orgIn: ruleOrgIn,
  emailContains: ruleEmailDomain,
  versionGte: { attribute: "app_version", operator: "gte", value: "2.0.0" } satisfies FeatureFlagRule,
  planEquals: { attribute: "plan", operator: "eq", value: "pro" } satisfies FeatureFlagRule,
} as const;

const variantOn = { key: "on", value: true, weight: 70 } as const satisfies FeatureFlagVariant;
const variantOff = { key: "off", value: false, weight: 30 } as const satisfies FeatureFlagVariant;

export const featureFlagVariantExamples = {
  on: variantOn,
  off: variantOff,
  control: { key: "control", value: "A" } satisfies FeatureFlagVariant,
  treatment: { key: "treatment", value: "B", weight: 50 } satisfies FeatureFlagVariant,
} as const;

export const featureFlagExamples = {
  simpleBoolean: {
    key: "new-checkout-flow",
    enabled: true,
    description: "Enable the rewritten checkout flow.",
  } satisfies FeatureFlag,
  withRules: {
    key: "beta-features",
    enabled: true,
    description: "Beta features gated to specific orgs.",
    rules: [ruleOrgIn, ruleEmailDomain],
  } satisfies FeatureFlag,
  abTest: {
    key: "checkout-experiment",
    enabled: true,
    description: "A/B test for checkout button color.",
    variants: [variantOn, variantOff],
  } satisfies FeatureFlag,
  fullyTargeted: {
    key: "enterprise-features",
    enabled: true,
    description: "Enterprise tier features.",
    variants: [featureFlagVariantExamples.control, featureFlagVariantExamples.treatment],
    rules: [{ attribute: "plan", operator: "eq", value: "enterprise" }],
  } satisfies FeatureFlag,
  disabled: { key: "old-feature", enabled: false } satisfies FeatureFlag,
} as const;

export const featureFlagEvaluationExamples = {
  enabled: {
    key: "new-checkout-flow",
    enabled: true,
    reason: "rule_matched",
  } satisfies FeatureFlagEvaluation,
  withVariant: {
    key: "checkout-experiment",
    enabled: true,
    variant: "on",
    reason: "variant_assigned",
  } satisfies FeatureFlagEvaluation,
  disabled: {
    key: "old-feature",
    enabled: false,
    reason: "flag_disabled",
  } satisfies FeatureFlagEvaluation,
  defaulted: { key: "missing-flag", enabled: false } satisfies FeatureFlagEvaluation,
} as const;
```
