---
title: Generating TypeScript Interfaces
label: Generating Types
order: 20
desc: Generate your own TypeScript interfaces based on your collections and globals.
keywords: headless cms, typescript, documentation, Content Management System, cms, headless, javascript, node, react, express
---

While building your own custom functionality into Payload, like plugins, hooks, access control functions, custom routes, GraphQL queries / mutations, or anything else, you may benefit from generating your own TypeScript types dynamically from your Payload config itself.

### Types generatation script

Run the following command in a Payload project to generate types based on your Payload config:

```
payload generate:types
```

You can run this command whenever you need to regenerate your types, and then you can use these types in your Payload code directly.

### Configuration

In order for Payload to properly infer these types when using local operations, you'll need to alias the following in your tsconfig.json file:

```json
// tsconfig.json

{
  "compilerOptions": {
    // ...
    "paths": {
      "payload/generated-types": [
        "./src/payload-types.ts" // Ensure this matches the path to your typescript outputFile
      ]
    }
  }
  // ...
}
```

#### Custom output file path

You can specify where you want your types to be generated by adding a property to your Payload config:

```ts
// payload.config.ts

{
  // ...
	typescript: {
    // defaults to: path.resolve(__dirname, './payload-types.ts')
		outputFile: path.resolve(__dirname, './generated-types.ts'),
	},
}
```

The above example places your types next to your Payload config itself as the file `generated-types.ts`.

### Example Usage

For example, let's look at the following simple Payload config:

```ts
const config: Config = {
  serverURL: process.env.PAYLOAD_PUBLIC_SERVER_URL,
  admin: {
    user: 'users',
  }
  collections: [
    {
      slug: 'users',
      fields: [
        {
          name: 'name',
          type: 'text',
          required: true,
        }
      ]
    },
    {
      slug: 'posts',
      admin: {
        useAsTitle: 'title',
      },
      fields: [
        {
          name: 'title',
          type: 'text',
        },
        {
          name: 'author',
          type: 'relationship',
          relationTo: 'users',
        },
      ]
    }
  ]
}
```

By generating types, we'll end up with a file containing the following two TypeScript interfaces:

```ts
export interface User {
  id: string;
  name: string;
  email?: string;
  resetPasswordToken?: string;
  resetPasswordExpiration?: string;
  loginAttempts?: number;
  lockUntil?: string;
}

export interface Post {
  id: string;
  title?: string;
  author?: string | User;
}
```

### Custom Field Interfaces

For `array`, `block`, `group` and named `tab` fields, you can generate top level reusable interfaces. The following group field config:

```ts
{
  type: 'group',
  name: 'meta',
  interfaceName: 'SharedMeta', <-- here!!
  fields: [
    {
      name: 'title',
      type: 'text',
    },
    {
      name: 'description',
      type: 'text',
    },
  ],
}
```

will generate:

```ts
// a top level reusable interface!!
export interface SharedMeta {
  title?: string;
  description?: string;
}

// example usage inside collection interface
export interface Collection1 {
  // ...other fields
  meta?: SharedMeta;
}
```

<Banner type="warning">
  <strong>Naming Collisions</strong>
  <br />
  Since these types are hoisted to the top level, you need to be aware that
  naming collisions can occur. For example, if you have a collection with the
  name of `Meta` and you also create a interface with the name `Meta` they will
  collide. It is recommended to scope your interfaces by appending the field
  type to the end, i.e. `MetaGroup` or similar.
</Banner>

### Using your types

Now that your types have been generated, payloads local API will now be typed. It is common for users to want to use this in their frontend code, we recommend generating them with payload and then copying the file over to your frontend codebase. This is the simplest way to get your types into your frontend codebase.

#### Adding an NPM script

<Banner type="warning">
  <strong>Important</strong>
  <br />
  Payload needs to be able to find your config to generate your types.
</Banner>

Payload will automatically try and locate your config, but might not always be able to find it. For example, if you are working in a `/src` directory or similar, you need to tell Payload where to find your config manually by using an environment variable. If this applies to you, you can create an NPM script to make generating your types easier.

To add an NPM script to generate your types and show Payload where to find your config, open your `package.json` and update the `scripts` property to the following:

```
{
  "scripts": {
    "generate:types": "PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:types",
  },
}
```

Now you can run `yarn generate:types` to easily generate your types.
