Page updated Mar 13, 2024

Add fields to data model

Amplify Data supports all AWS AppSync scalar types as field types. The following scalar types are available:

Field typeDescriptionTypeScript validationGraphQL Scalar Type
a.id()A unique identifier for an object. This scalar is serialized like a String but isn't meant to be human-readable. If not specified on create operations, a UUID will be generated.stringID
a.string()A UTF-8 character sequence.stringString
a.integer()An integer value between -(2^31) and 2^31-1.number but rounded to closest integer value upon query/mutationInt
a.float()An IEEE 754 floating point value.numberFloat
a.boolean()A Boolean value, either true or false.booleanBoolean
a.date()An extended ISO 8601 date string in the format YYYY-MM-DD.Date but time information is cleared upon query/mutationAWSDate
a.time()An extended ISO 8601 time string in the format hh:mm:ss.sss.Date but date information is removed upon query/mutationAWSTime
a.datetime()An extended ISO 8601 date and time string in the format YYYY-MM-DDThh:mm:ss.sssZ.DateAWSDateTime
a.timestamp()An integer value representing the number of seconds before or after 1970-01-01-T00:00Z.numberAWSTimestamp
a.email()An email address in the format local-part@domain-part as defined by RFC 822.string with local-part and domain-part type enforcementAWSEmail
a.json()A JSON string. Any valid JSON construct is automatically parsed and loaded in the resolver code as maps, lists, or scalar values, rather than as the literal input strings. Unquoted strings or otherwise invalid JSON result in a validation error.anyAWSJSON
a.phone()A phone number. This value is stored as a string. Phone numbers can contain either spaces or hyphens to separate digit groups. Phone numbers without a country code are assumed to be US/North American numbers adhering to the North American Numbering Plan.string validation only happening service-sideAWSPhone
a.url()A URL as defined by RFC 1738. For example, https://www.amazon.com/dp/B000NZW3KC/ or mailto:example@example.com. URLs must contain a schema (http, mailto) and can't contain two forward slashes (//) in the path part.string but with type enforcement on the schema partAWSURL
a.ipAddress()A valid IPv4 or IPv6 address. IPv4 addresses are expected in quad-dotted notation (123.12.34.56). IPv6 addresses are expected in non-bracketed, colon-separated format (1a2b:3c4b:1234:4567). You can include an optional CIDR suffix (123.45.67.89/16) to indicate subnet mask.string with type enforcement for IPv4 and IPv6 patternAWSIPAddress

Specify a custom field type

Sometimes, the built-in types do not meet the needs of your application. In those cases, you can specify custom types. You can either define the custom types inline or explicitly define the custom type in the schema.

Inline definition: The "location" field will become a new non-model type that uses PascalCase, a naming convention in which the first letter of each word in a compound word is capitalized. If there are conflicts with another schema-level definition (model, custom type, enum), you will receive a Type error with a warning that you need to sift the value out as a separate item and use a "ref".

1a.schema({
2 Post: a.model({
3 location: a.customType({
4 lat: a.float(),
5 long: a.float(),
6 }),
7 content: a.string(),
8 }),
9});

Explicit definition: Specify the "Location" as a.customType() in your schema. To use the custom type, reference it through a.ref() in the respective field definitions.

1a.schema({
2 Location: a.customType({
3 lat: a.float(),
4 long: a.float(),
5 }),
6
7 Post: a.model({
8 location: a.ref('Location'),
9 content: a.string(),
10 }),
11
12 User: a.model({
13 lastKnownLocation: a.ref('Location'),
14 }),
15});

To set or read the location field on the client side, you can expand a nested object and the type system will auto-infer the allowed values.

1const newPost = await client.models.Post.create({
2 location: {
3 lat: 48.837006,
4 long: 8.282450,
5 }
6});
7
8console.log(newPost.location.lat, newPost.location.long)

Specify an enum field type

Enum has a similar developer experience as custom types: short-hand and long-form approaches. To make building a dropdown UI easier, you can also retrieve all available enum options from your client code.

1a.schema({
2 Post: a.model({
3 privacySetting: a.enum(['PRIVATE', 'FRIENDS_ONLY', 'PUBLIC']),
4 content: string(),
5 }),
6});
1a.schema({
2 PrivacySetting: a.enum([
3 'PRIVATE',
4 'FRIENDS_ONLY',
5 'PUBLIC'
6 ]),
7
8 Post: a.model({
9 content: string(),
10 privacySetting: a.ref('PrivacySetting'),
11 }),
12
13 Video: a.model({
14 privacySetting: a.ref('PrivacySetting'),
15 }),
16});

When creating a new item client-side, the enums are also type-enforced:

1client.models.Post.create({
2 content: 'hello',
3 // WORKS - value auto-completed
4 privacySetting: 'PRIVATE',
5
6 // DOES NOT WORK - TYPE ERROR
7 privacySetting: 'NOT_PUBLIC',
8});

List enum values client-side

You can list available enum values client-side using the client.enums.<ENUM_NAME>.values() API. For example, this allows you to display the available enum values within a dropdown UI.

1const availableSettings = client.enums.PrivacySetting.values()
2// availableSettings returns ["PRIVATE", "FRIENDS_ONLY", "PUBLIC"]

Mark fields as required

By default, fields are optional. To mark a field as required, use the .required() modifier.

1const schema = a.schema({
2 Todo: a.model({
3 content: a.string().required(),
4 }),
5});

Mark fields as arrays

Any field can be modified to be an array using the .array() modifier.

1const schema = a.schema({
2 Todo: a.model({
3 content: a.string().required(),
4 notes: a.string().array(),
5 }),
6});

Assign default values for fields

You can use the .default(...) modifier to specify a default value for optional scalar type fields and arrays. The .default(...) modifier is not available for custom types, enums, or relationships.

1const schema = a.schema({
2 Todo: a.model({
3 content: a.string().default('My new Todo'),
4 }),
5});

Note: The .default(...) modifier can't be applied to required fields.