# Schemas

Schemas are an optional description of the structure of a resource type. Defining a schema allows you to use more features of Standard Resource. They also can help you to prevent certain kinds of bugs.

Keep in mind: schemas are entirely optional. You may decide to start using Standard Resource *without* schemas, and then add them in later. Or maybe you never add them. That is okay.

### Defining a Schema

A schema is a JavaScript object. The simplest schema, then, is just an empty object:

```javascript
{
}
```

Although an empty object is a valid schema, it isn't particularly useful as it doesn't do anything!

In this guide, we will cover all of the properties of a schema.

### Using a Schema

Once you have your schemas defined, you can add it to your store when you create the store using the second argument to [`createResourceStore()`](/api-reference/createresourcestore.md). In this example, we add a few schemas to our store:

```javascript
import createResourceStore from 'standard-resource';
import books from './schemas/books';
import authors from './schemas/authors';

export default createResourceStore(null, {
  schemas: {
    books,
    authors,
  },
});
```

> You cannot add, change, or remove schemas after the store has been created.

## Schema Properties

The rest of this guide will describe the different properties of a schema.

### `idType`

This defines what the data type is of the resource IDs. There are three valid values:

* `"string"`: The ID is a string
* `"number"`: The ID is a number
* `["string", "number"]`: The ID can be either a string or a number

By default, the `idType` is `["string", "number"]`.

```javascript
export default {
  idType: 'string',
};
```

### `idProperty`

The name of the ID property. By default, it is `"id"`.

Sometimes, servers return IDs on a different property, such as `"bookId"`. You have two choices in these situations: rename it to `"id"`, or specify the `"idProperty"` in the schema.

```javascript
export default {
  idProperty: 'bookId',
};
```

### `attributes`

The `attributes` property allows you to specify the types of the resource's attributes. This can help you to prevent bugs in your app.

For instance, if your resource has a name that should always be a string, then you can specify that here. Then, if you update the state with a name that is something other than a string, you will be warned.

To specify your attribute types, you should use the [PropTypes](https://github.com/facebook/prop-types) library.

```javascript
import PropTypes from 'prop-types';

export default {
  attributes: {
    name: PropTypes.string,
    year: PropTypes.number,
  },
};
```

To take full advantage of the `attributes` property, we encourage you to familiarize yourself with the PropTypes library by reading its [documentation](https://github.com/facebook/prop-types#usage).

### `meta`

This property is identical in structure to `attributes`, except that it applies to the [resource metadata](/resources/resource-data.md#meta) instead.

```javascript
import PropTypes from 'prop-types';

export default {
  meta: {
    isSelected: PropTypes.bool,
  },
};
```

### `computedAttributes`

Computed attributes allow you to specify the computed attributes for your resource. We encourage you to read [the guide](/resources/using-computed-attributes.md) on computed attributes to learn more about them.

In this example, we define a display name that is computed from the first and last name of the resource.

```javascript
export default {
  computedAttributes: {
    displayName(resource) {
      return `${resource.firstName} ${resource.lastName[0]}`;
    },
  },
};
```

In this example, we use the Reselect library to memoize a slow computed computed:

```javascript
import createSelector from 'reselect';

export default {
  computedAttributes: {
    sortedItems: createSelector(
      resource => resource.attributes.items,
      items => sortItemsAlphabetically(items)
    ),
  },
};
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://standard-resource.js.org/resources/schemas.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
