# Control Property Naming and Casing
Source: https://speakeasy.com/docs/sdks/customize/typescript/property-naming

import { Callout } from "@/mdx/components";



TypeScript SDKs support configurable property naming to match your API's field naming conventions. You can either normalize property names to a consistent casing style, or preserve the exact names from your OpenAPI spec.

## Property Casing

Use `modelPropertyCasing` to control whether generated TypeScript types use camelCase or snake_case property names.

### Configuration

```yaml filename="<sdk-root>/.speakeasy/gen.yaml"
typescript:
  modelPropertyCasing: "camel" # or "snake"
```

### Options

- **`camel` (default)**: Properties use camelCase naming (e.g., `firstName`, `createdAt`)
- **`snake`**: Properties use snake_case naming (e.g., `first_name`, `created_at`)

### Examples

**camelCase naming (default)**
```typescript
// Configuration: modelPropertyCasing: "camel"
export type User = {
    id: string;
    firstName: string;
    lastName: string;
    emailAddress: string;
    createdAt: Date;
    isActive: boolean;
};
```

**snake_case naming**
```typescript
// Configuration: modelPropertyCasing: "snake"
export type User = {
    id: string;
    first_name: string;
    last_name: string;
    email_address: string;
    created_at: Date;
    is_active: boolean;
};
```

## Preserve Original Property Names

Use `preserveModelFieldNames` to keep the exact property names from your OpenAPI spec without any normalization. This is useful when:

- Your API uses unconventional naming (e.g., properties starting with `_`)
- You need exact parity with existing SDKs or API documentation
- Your property names have special meaning that would be lost through normalization

### Configuration

```yaml filename="<sdk-root>/.speakeasy/gen.yaml"
typescript:
  preserveModelFieldNames: true
```

<Callout title="Interaction with modelPropertyCasing" type="info">
  When `preserveModelFieldNames` is enabled, `modelPropertyCasing` only affects synthetic fields generated by Speakeasy (like `additionalProperties`, `clientID`, etc.). Properties defined in your OpenAPI spec will use their original names exactly as specified.
</Callout>

### Example

Given an OpenAPI spec with these properties:

```yaml
components:
  schemas:
    Event:
      type: object
      properties:
        _raw:
          type: string
        __metadata:
          type: object
        event_type:
          type: string
        EventID:
          type: string
```

**Without preservation (default):**
```typescript
// preserveModelFieldNames: false (default)
// Properties are normalized based on modelPropertyCasing
export type Event = {
    raw: string;        // Leading underscores removed
    metadata: object;   // Leading underscores removed
    eventType: string;  // Converted to camelCase
    eventId: string;    // Converted to camelCase
};
```

**With preservation:**
```typescript
// preserveModelFieldNames: true
// Properties match OpenAPI spec exactly
export type Event = {
    _raw: string;       // Preserved with underscore
    __metadata: object; // Preserved with underscores
    event_type: string; // Preserved as snake_case
    EventID: string;    // Preserved as PascalCase
};
```

### When to Use

| Scenario | Recommendation |
|----------|----------------|
| Standard APIs with conventional naming | Use `modelPropertyCasing` (default) |
| APIs with leading underscores (e.g., `_raw`, `_links`) | Use `preserveModelFieldNames: true` |
| Migrating from existing SDK with specific field names | Use `preserveModelFieldNames: true` |
| Mixed naming conventions that must be preserved | Use `preserveModelFieldNames: true` |