# Circular reference

Sometimes we may need to have a type reference itself in its attributes, or have two types that reference eachother in separate files, it can be a complication because it's not possible to do this using the type definitions like we did before. For cases like this we can use a feature called "dynamic types".

When using dynamic types you can pass a string instead of the type itself in the type definition, this string will contain the type **identifier**, and then pass an object as the *second* parameter of the `attributes` function with a key `dynamics` where the concrete type for each identifier is declared:

```javascript
/*
 * User.js
 */
const User = attributes(
  {
    name: String,
    friends: {
      type: Array,
      itemType: 'User', // << identifier
    },
    favoriteBook: {
      type: 'BookStructure', // << identifier
      required: true,
    },
    books: {
      type: 'BooksCollection', // << identifier
      itemType: String,
    },
  },
  {
    dynamics: {
      /* dynamic types for each identifier */
      User: () => User,
      BookStructure: () => require('./Book'),
      BooksCollection: () => require('./BooksCollection'),
    },
  }
)(class User {});

module.exports = User;

/*
 * Book.js
 */
const Book = attributes(
  {
    name: String,
    owner: 'User', // << dynamic type with inferred identifier
    nextBook: 'BookStructure', // << dynamic type with custom identifier
  },
  {
    identifier: 'BookStructure', // << custom identifier
    dynamics: {
      /* dynamic types for each identifier */
      User: () => require('./User'),
      BookStructure: () => Book,
    },
  }
)(class Book {});

module.exports = Book;
```

If you're using `import` instead of `require` (thus having to import the dynamic value in the top-level of the file), go to the [With ES Modules](/schema-concept/circular-references-and-dynamic-types.md#with-es-modules) section of this page.

## Dynamic type identifier

The type's identifier has to be same everywhere it's used, and can be defined in two ways:

### Inferred identifier

The identifier can be inferred based on the class that is wrapped by the `attributes` function. In backend scenarios this will be the most common case:

```javascript
const User = attributes(
  {
    name: String,
    bestFriend: 'User', // [A] type with inferred identifier
  },
  {
    dynamics: {
      User: () => User, // [B] inferred identifier concrete type
    },
  }
)(
  class User {
    //   ⬑-- the name of this class is the identifier
    // so if we change this name to UserEntity, we'll have to change
    // both [A] and [B] to use the string 'UserEntity' instead of 'User'
  }
);
```

### Custom identifier

If for some reason you can't rely on the class name, be it because you're using a compiler that strips class names or creates a dynamic one, you can explicitly set an indentifier.

To do that, in the second argument of the `attributes` function (e.g. the options) you should add a `identifier` key and set it to be the string with the type's identifier and then use that custom value everywhere this type is dynamically needed:

```javascript
const User = attributes(
  {
    name: String,
    bestFriend: 'UserEntity', // << type with custom identifier
  },
  {
    identifier: 'UserEntity', // << custom identifier
    dynamics: {
      // ⬐--- custom identifier concrete type
      UserEntity: () => User,
    },
  }
)(class User {});
```

## Concrete type definition inside `dynamics`

For the cases where the dynamic type is in a different file, it's important that the actual needs type to be resolved **inside** the function with the identifier. Let's break it down in two cases:

### With CommonJS modules

When using CommonJS modules you have two possibilities:

1. Putting the `require` call directly inside the concrete type resolution function:

```javascript
const Book = attributes(
  {
    name: String,
    owner: 'User',
    nextBook: 'BookStructure',
  },
  {
    identifier: 'BookStructure',
    dynamics: {
      User: () => require('./User'), // << like this
      BookStructure: () => Book,
    },
  }
)(class Book {});

module.exports = Book;
```

1. Exporting an **object** containing your other structure (instead of exporting the structure itself) and only access it inside the concrete type resolution function:

```javascript
/*
 * User.js
 */
const BookModule = require('./Book');

const User = attributes(
  {
    name: String,
    favoriteBook: {
      type: 'Book',
      required: true,
    },
  },
  {
    dynamics: {
      User: () => User,
      Book: () => BookModule.Book,
    },
  }
)(class User {});

exports.User = User;

/*
 * Book.js
 */
const UserModule = require('./User');

const Book = attributes(
  {
    name: String,
    owner: 'User',
  },
  {
    dynamics: {
      User: () => UserModule.User,
      Book: () => Book,
    },
  }
)(class Book {});

exports.Book = Book;
```

### With ES Modules

When using ES Modules you have a single possibility, which is importing the other structure from the top-level of your file and then returning it from the concrete type resolution function. It's important to note that this **only** works with ES Modules, if you're using CommonJS, check the [With CommonJS modules](/schema-concept/circular-references-and-dynamic-types.md#with-commonjs-modules) section.

```javascript
/*
 * User.js
 */
import Book from './Book';

const User = attributes(
  {
    name: String,
    favoriteBook: {
      type: 'Book',
      required: true,
    },
  },
  {
    dynamics: {
      User: () => User,
      Book: () => Book,
    },
  }
)(class User {});

export default User;

/*
 * Book.js
 */
import User from './User';

const Book = attributes(
  {
    name: String,
    owner: 'User',
  },
  {
    dynamics: {
      User: () => User,
      Book: () => Book,
    },
  }
)(class Book {});

export default Book;
```


---

# 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://structure.js.org/schema-concept/circular-references-and-dynamic-types.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.
