Types
Built-in types
string
integer
long
double
boolean
datetime
An RFC 3339, section 5.6 datetime. For example,2017-07-21T17:32:28Z
.date
An RFC 3339, section 5.6 date (YYYY-MM-DD). For example,2017-07-21
.uuid
base64
list
e.g. list<string>set
e.g. set<string>map
e.g. map<string, integer>optional
e.g. optional<string>
unknown
Fern comes with a special type unknown
, which signifies that the type cannot
be represented in Fern. Often, this is because the value has a dynamic shape
(e.g. user-supplied data).
In cases where you use unknown
, Fern will assume the value is optional. There’s
no difference between unknown
and optional<unknown>
.
Custom types
Creating your own types is easy in Fern!
Objects
The most common custom types are objects.
In Fern, you use the "properties"
key to create an object:
types:
Person:
properties: # <---
name: string
address: Address
Address:
properties: # <---
line1: string
line2: optional<string>
city: string
state: string
zip: string
These represent JSON objects:
{
"name": "Alice",
"address": {
"line1": "123 Happy Lane",
"city": "New York",
"state": "NY",
"zip": "10001"
}
}
You can also use extends to compose objects:
types:
Pet:
properties:
name: string
Dog:
extends: Pet
properties:
breed: string
Aliases
An Alias type is a renaming of an existing type. This is usually done for clarity.
types:
# UserId is an alias of string
UserId: string
User:
properties:
id: UserId
name: string
Enums
An enum represents a string with a set of allowed values.
In Fern, you use the "enum"
key to create an enum:
types:
WeatherReport:
enum: # <---
- SUNNY
- CLOUDY
- RAINING
- SNOWING
Unions
Fern supports tagged unions (a.k.a. discriminated unions). Unions are useful for
polymorphism. This is similar to the oneOf
concept in OpenAPI.
In Fern, you use the "union"
key to create an union:
types:
Animal:
union:
dog: Dog
cat: Cat
Dog:
properties:
likesToWoof: boolean
Cat:
properties:
likesToMeow: boolean
In JSON, unions have a discriminant property to differentiate between
different members of the union. By default, Fern uses "type"
as the
discriminant property:
{
"type": "dog",
"likesToWoof": true
}
You can customize the discriminant property using the “discriminant” key:
types:
Animal:
+ discriminant: animalType
union:
dog: Dog
cat: Cat
Dog:
properties:
likesToWoof: boolean
Cat:
properties:
likesToMeow: boolean
This corresponds to a JSON object like this:
{
"animalType": "dog",
"likesToWoof": true
}
Documentation
You can add documentation for types. These docs are passed into the compiler, and are incredibly useful in the generated outputs (e.g. docstrings in SDKs).
types:
Person:
docs: A person represents a human being
properties:
name: string
age:
docs: age in years
type: integer
/**
* A person represents a human being
*/
interface Person {
name: string;
// age in years
age: number;
}
Examples
You can add examples for types. These are passed into the compiler to be used in the generated outputs (e.g. examples in the Postman Collection).
types:
UserId:
docs: A unique identifier for a user
type: string
examples:
- value: user-id-123
/**
* A unique identifier for a user
*
* @example "user-id-123"
*/
type UserId = string;
The Fern compiler validates that your examples match the expected types. For example, this won’t compile:
types:
UserId:
type: integer
examples:
- value: hello # not an integer
Referencing examples from other types
Just like types, you can compose examples. To reference an example from another
type, use $
.
types:
UserId:
type: integer
examples:
- name: Example1
value: user-id-123
User:
properties:
id: UserId
name: string
examples:
- value:
id: $UserId.Example1 # <---
name: Jane Smith