Skip to content

Commit 4dcce4a

Browse files
docs: add documentation for nullable types and explicit null overrides
- Add nullable<T> to built-in types table - Document the difference between optional and nullable - Explain PATCH request semantics with explicit null values - Provide TypeScript and Java SDK usage examples - Document combining optional and nullable for three-state fields This addresses the need to document explicit null overrides for APIs that need to differentiate between omitted fields, explicit null values, and actual values in PATCH requests. Co-Authored-By: Devin Logan <[email protected]>
1 parent a68f023 commit 4dcce4a

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

fern/products/api-def/ferndef-pages/types.mdx

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,87 @@ Types describe the data model of your API.
2222
| `set` | An unordered collection with unique elements, e.g., `set<string>` |
2323
| `map` | Key-value mapping, e.g., `map<string, integer>` |
2424
| `optional` | Optional value, e.g., `optional<string>` |
25+
| `nullable` | Nullable value that can be explicitly set to `null`, e.g., `nullable<string>` |
2526
| `literal` | Literal value, e.g., `literal<"Plants">` |
2627
| `file` | File upload type, e.g., [file uploads](/learn/api-definition/fern/endpoints/multipart) |
2728
| `unknown` | Represents arbitrary JSON |
2829

30+
### Optional vs Nullable
31+
32+
Understanding the difference between `optional` and `nullable` is important for properly modeling your API:
33+
34+
- **`optional<T>`**: The field can be omitted from the request/response entirely. When omitted, the field is not sent over the wire.
35+
- **`nullable<T>`**: The field must be present but can be explicitly set to `null`. This allows you to distinguish between "not specified" and "explicitly cleared".
36+
37+
```yaml
38+
types:
39+
User:
40+
properties:
41+
name: string
42+
nickname: optional<string> # Can be omitted entirely
43+
bio: nullable<string> # Must be present, but can be null
44+
```
45+
46+
This distinction is particularly important for PATCH requests where you need to differentiate between:
47+
1. **Omitting a field** - Don't update this field (keep existing value)
48+
2. **Setting to `null`** - Clear this field (remove the value)
49+
3. **Setting to a value** - Update this field with a new value
50+
51+
#### Example: PATCH request semantics
52+
53+
```yaml
54+
types:
55+
UpdateUserRequest:
56+
properties:
57+
nickname: optional<string> # Omit to keep current nickname
58+
bio: nullable<string> # Set to null to clear bio
59+
```
60+
61+
**TypeScript SDK usage:**
62+
```typescript
63+
// Don't update nickname, clear bio
64+
await client.users.update({
65+
bio: null // Explicitly clear the bio field
66+
// nickname is omitted, so it won't be updated
67+
});
68+
69+
// Update both fields
70+
await client.users.update({
71+
nickname: "john_doe",
72+
bio: "Software engineer"
73+
});
74+
```
75+
76+
**Java SDK usage:**
77+
```java
78+
// With collapse-optional-nullable config enabled
79+
UpdateUserRequest.builder()
80+
.nickname(Optional.empty()) // Omit field (don't update)
81+
.bio(OptionalNullable.ofNull()) // Clear field (set to null)
82+
.build();
83+
84+
UpdateUserRequest.builder()
85+
.nickname(Optional.of("john_doe"))
86+
.bio(OptionalNullable.of("Software engineer"))
87+
.build();
88+
```
89+
90+
### Combining optional and nullable
91+
92+
You can combine `optional` and `nullable` to create a field that can be omitted OR explicitly set to null:
93+
94+
```yaml
95+
types:
96+
User:
97+
properties:
98+
metadata: optional<nullable<map<string, string>>>
99+
```
100+
101+
This creates three possible states:
102+
1. Field omitted entirely
103+
2. Field present with `null` value
104+
3. Field present with actual map data
105+
29106
## Custom types
30107

31108
Creating your own types is easy in Fern!

0 commit comments

Comments
 (0)