# TypeScript - Manipulating Documents and Entries

> Source: https://docs.strapi.io/cms/typescript/documents-and-entries

Safely manipulate documents and entries in Strapi v5 TypeScript projects using the `UID` and `Data` namespaces for type safety, enabling both generic and known entity type operations with code completion.

This guide will explore [TypeScript](/cms/typescript) patterns for manipulating documents and entries in a Strapi v5 application, including how to leverage Strapi's `UID` and `Data` namespaces to interact with both generic and known entity types safely. If you're working on a TypeScript-based Strapi project, mastering these approaches will help you take full advantage of type safety and code completion, ensuring robust, error-free interactions with your application’s content and components.

:::prerequisites

- **Strapi Application:** A Strapi v5 application. If you don't have one, follow the [documentation](/cms/quick-start) to get started.
- **TypeScript:** Ensure TypeScript is set up in your Strapi project. You can follow Strapi's [official guide](/cms/typescript#getting-started-with-typescript-in-strapi) on configuring TypeScript.
- **Generated Types:** Application types [have been generated](/cms/typescript/development#generate-typings-for-content-types-schemas) and are accessible.
  :::

## Type Imports

The `UID` namespace contains literal unions representing the available resources in the application.

```typescript

```

- `UID.ContentType` represents a union of every content-type identifier in the application
- `UID.Component` represents a union of every component identifier in the application
- `UID.Schema` represents a union of every schema (content-type or component) identifier in the application
- And others...

---

Strapi provides a `Data` namespace containing several built-in types for entity representation.

```typescript

```

- `Data.ContentType` represents a Strapi document object
- `Data.Component` represents a Strapi component object
- `Data.Entity` represents either a document or a component

:::tip
Both the entities' type definitions and UIDs are based on the generated schema types for your application.

In case of a mismatch or error, you can always [regenerate the types](/cms/typescript/development#generate-typings-for-content-types-schemas).
:::

## Usage

<br />

### Generic entities

When dealing with generic data, it is recommended to use non-parametrized forms of the `Data` types.

#### Generic documents

```typescript
async function save(name: string, document: Data.ContentType) {
  await writeCSV(name, document);
  //                    ^ {
  //                        id: Data.ID;
  //                        documentId: string;
  //                        createdAt?: DateTimeValue;
  //                        updatedAt?: DateTimeValue;
  //                        publishedAt?: DateTimeValue;
  //                        ...
  //                      }
}
```

:::warning
In the preceding example, the resolved properties for `document` are those common to every content-type.

Other properties have to be checked manually using type guards.

```typescript
if ('my_prop' in document) {
  return document.my_prop;
}
```

:::

#### Generic components

```typescript
function renderComponent(parent: Node, component: Data.Component) {
  const elements: Element[] = [];
  const properties = Object.entries(component);

  for (const [name, value] of properties) {
    //        ^        ^
    //        string   any
    const paragraph = document.createElement('p');

    paragraph.textContent = `Key: ${name}, Value: ${value}`;

    elements.push(paragraph);
  }

  parent.append(...elements);
}
```

### Known entities

When manipulating known entities, it is possible to parametrize `Data` types for better type safety and code completion.

#### Known documents

```typescript
const ALL_CATEGORIES = ['food', 'tech', 'travel'];

function validateArticle(article: Data.ContentType<'api::article.article'>) {
  const { title, category } = article;
  //       ^?         ^?
  //       string     Data.ContentType<'api::category.category'>

  if (title.length < 5) {
    throw new Error('Title too short');
  }

  if (!ALL_CATEGORIES.includes(category.name)) {
    throw new Error(`Unknown category ${category.name}`);
  }
}
```

#### Known components

```typescript
function processUsageMetrics(
  id: string,
  metrics: Data.Component<'app.metrics'>
) {
  telemetry.send(id, { clicks: metrics.clicks, views: metrics.views });
}
```

### Advanced use cases

<br/>

#### Entities subsets

Using the types' second parameter (`TKeys`), it is possible to obtain a subset of an entity.

```typescript
type Credentials = Data.ContentType<'api::account.account', 'email' | 'password'>;
//   ^? { email: string; password: string }
```

```typescript
type UsageMetrics = Data.Component<'app.metrics', 'clicks' | 'views'>;
//   ^? { clicks: number; views: number }
```

#### Type argument inference

It is possible to bind and restrict an entity type based on other function parameters.

In the following example, the `uid` type is inferred upon usage as `T` and used as a type parameter for the `document`.

```typescript

function display<T extends UID.ContentType>(
  uid: T,
  document: Data.ContentType<T>
) {
  switch (uid) {
    case 'api::article.article': {
      return document.title;
      //              ^? string
      //     ^? Data.ContentType<'api::article.article'>
    }
    case 'api::category.category': {
      return document.name;
      //              ^? string
      //     ^? Data.ContentType<'api::category.category'>
    }
    case 'api::account.account': {
      return document.email;
      //              ^? string
      //     ^? Data.ContentType<'api::account.account'>
    }
    default: {
      throw new Error(`unknown content-type uid: "${uid}"`);
    }
  }
}
```

When calling the function, the `document` type needs to match the given `uid`.

```typescript
declare const article: Data.Document<'api::article.article'>;
declare const category: Data.Document<'api::category.category'>;
declare const account: Data.Document<'api::account.account'>;

display('api::article.article', article);
display('api::category.category', category);
display('api::account.account', account);
// ^ ✅

display('api::article.article', category);
// ^ Error: "category" is not assignable to parameter of type ContentType<'api::article.article'>
```
