> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://buildwithfern.com/learn/llms.txt. # Types in Fern Definition > Types describe the data model of your API. Fern has many built-in types and supports custom types, as well as extending and aliasing objects, and unions. Fern Definition isn't recommended for new customers and Fern isn't accepting feature requests for this format. It remains supported for existing users. Types describe the data model of your API. ## Built-in types | Type | Description | | ---------- | ------------------------------------------------------------------------------------------------------------------- | | `string` | Basic string type | | `integer` | Integer number type | | `long` | Long integer type | | `double` | Double precision floating point | | `boolean` | Boolean true/false | | `datetime` | An [RFC 3339, section 5.6 datetime](https://ijmacd.github.io/rfc3339-iso8601/). For example, `2017-07-21T17:32:28Z` | | `date` | An RFC 3339, section 5.6 date (YYYY-MM-DD). For example, `2017-07-21` | | `uuid` | UUID identifier | | `base64` | Base64 encoded data | | `list` | An ordered collection that allows duplicates, e.g., `list` | | `set` | An unordered collection with unique elements, e.g., `set` | | `map` | Key-value mapping, e.g., `map` | | `optional` | Optional value, e.g., `optional` | | `literal` | Literal value, e.g., `literal<"Plants">` | | `file` | File upload type, e.g., [file uploads](/learn/api-definitions/ferndef/endpoints/multipart) | | `unknown` | Represents arbitrary JSON | ## 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: ```yaml {3,8} types: Person: properties: name: string address: Address Address: properties: line1: string line2: optional city: string state: string zip: string country: literal<"USA"> ``` These represent JSON objects: ```json { "name": "Alice", "address": { "line1": "123 Happy Lane", "city": "New York", "state": "NY", "zip": "10001", "country": "USA" } } ``` You can also use **extends** to compose objects: ```yaml {6} types: Pet: properties: name: string Dog: extends: Pet properties: breed: string ``` You can extend multiple objects: ```yaml {3-5} types: GoldenRetriever: extends: - Dog - Pet properties: isGoodBoy: boolean ``` ### Aliases An Alias type is a renaming of an existing type. This is usually done for clarity. ```yaml 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: ```yaml {3} types: WeatherReport: enum: - SUNNY - CLOUDY - RAINING - SNOWING ``` Enum names are restricted to `A-Z`, `a-z`, `0-9`, and `_` to ensure that generated code can compile across all of the languages that Fern can output. If you have an enum that doesn't follow this convention, you can use the `"name"` key to specify a custom name: ```yaml types: Operator: enum: - name: LESS_THAN # <--- the name that will be used in SDKs value: '<' # <--- the value that will be serialized - name: GREATER_THAN value: '>' - name: NOT_EQUAL value: '!=' ``` ### Discriminated 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: ```yaml {3-5} 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: ```json { "type": "dog", "likesToWoof": true } ``` You can customize the discriminant property using the "discriminant" key: ```yaml {3} 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: ```json { "animalType": "dog", "likesToWoof": true } ``` ### Undiscriminated unions Undiscriminated unions are similar to discriminated unions, however you don't need to define an explicit discriminant property. ```yaml MyUnion: discriminated: false union: - string - integer ``` ### Generics Fern supports shallow generic objects, to minimize code duplication. You can define a generic for reuse like so: ```yaml MySpecialMapItem: properties: key: Key, value: Value, diagnostics: string ``` Now, you can instantiate generic types as a type alias: ```yml StringIntegerMapItem: type: Response StringStringMapItem: type: Response ``` You can now freely use this type as if it were any other type! Note, generated code will not use generics. The above example will be generated in typescript as: ```typescript type StringIntegerMapItem = { key: string, value: number, diagnostics: string } type StringStringMapItem = { key: string, value: string, diagnostics: string } ``` ### Documenting types 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). #### Fern Definition ```yaml types: Person: docs: A person represents a human being properties: name: string age: docs: age in years type: integer ``` #### Generated TypeScript SDK from Fern Definition ```typescript /** * A person represents a human being */ interface Person { name: string; // age in years age: number; } ``` ### Validating types You can add validation constraints to your types (both aliases and references) to ensure data integrity. These validation constraints exist in your API definition and are enforced by the server, but the generated client SDKs don't include validation logic. #### Fern Definition ```yaml {8-11, 15-17} types: Person: docs: A person represents a human being properties: name: docs: The person's full name type: string validation: minLength: 2 maxLength: 100 pattern: "^[A-Za-z ]+$" age: docs: Age in years type: integer validation: min: 0 max: 150 ``` #### String validation reference String types support several validation constraints. ```yaml {4-6, 11-13, 16-19} types: Word: type: string validation: minLength: 2 maxLength: 26 User: properties: email: type: string validation: format: email maxLength: 254 username: type: string validation: minLength: 3 maxLength: 20 pattern: "^[a-zA-Z0-9_]+$" ``` **`minLength`** `integer` Minimum number of characters required --- **`maxLength`** `integer` Maximum number of characters allowed --- **`pattern`** `string` Regular expression pattern that the string must match --- **`format`** `string` String format specification (e.g., "email", "uri", "date-time") --- #### Number validation reference Number types (including `integer`, `long`, and `double`) support several validation constraints. ```yaml {4-6, 12-15, 18-20} types: Age: type: integer validation: min: 0 max: 150 Product: properties: name: string price: type: double validation: min: 0 exclusiveMin: true multipleOf: 0.01 quantity: type: integer validation: min: 1 max: 1000 ``` **`min`** `number` Minimum value (inclusive by default) --- **`max`** `number` Maximum value (inclusive by default) --- **`exclusiveMin`** `boolean` When true, the minimum value is exclusive (value must be greater than min) --- **`exclusiveMax`** `boolean` When true, the maximum value is exclusive (value must be less than max) --- **`multipleOf`** `number` Value must be a multiple of this number --- > Types describe the data model of your API. Fern has many built-in types and supports custom types, as well as extending and aliasing objects, and unions.