# Optional vs nullable fields

**An array of one object shape.**

## Input

```json
[
  { "id": 1, "middleName": "Byron", "deletedAt": null },
  { "id": 2, "deletedAt": "2026-01-05T00:00:00Z" }
]
```

## TypeScript

```typescript
export interface RootItem {
  id: number;
  middleName?: string;
  deletedAt: null | string;
}

export type Root = RootItem[];
```

## Zod

```typescript
import { z } from 'zod';

export const RootItemSchema = z.object({
  id: z.number(),
  middleName: z.string().optional(),
  deletedAt: z.string().nullable(),
});

export const RootSchema = z.array(RootItemSchema);
```

## Warnings

### Optionality inferred from one sample (caution)

`[].middleName` was missing from at least one object in the sample and is therefore marked optional. A single sample cannot distinguish "sometimes omitted" from "omitted in this particular payload".

**Fix:** Check these against the real schema. Absent means optional; a null value would instead mean present-and-nullable, which is a different type.

### Whole numbers are still `number` (info)

Every numeric value in the sample was a whole number, but JSON has a single number type and cannot express the difference. The output uses `number`.

**Fix:** If a field is genuinely an integer, tighten it by hand: `z.number().int()`.

---

Canonical URL: https://json-to-types.gumballtools.com/types/optional-vs-nullable
JSON API: `POST https://json-to-types.gumballtools.com/api/v1/convert`
MCP endpoint: `https://json-to-types.gumballtools.com/api/mcp`
