Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0a8e42b
Add API Reference and Guides for TypeScript in docs
Convly Oct 18, 2024
910186b
Add TypeScript guide for manipulating Strapi documents and entries
Convly Oct 18, 2024
638b2e7
Add new tags to TypeScript development docs
Convly Oct 18, 2024
e613ccb
Update docusaurus/docs/dev-docs/typescript/development/guides/documen…
pwizla Oct 23, 2024
da7e842
Update docusaurus/docs/dev-docs/typescript/development/guides/documen…
pwizla Oct 23, 2024
e797774
Update docusaurus/docs/dev-docs/typescript/development/guides/documen…
pwizla Oct 23, 2024
7b41cef
Update docusaurus/docs/dev-docs/typescript/development/guides/documen…
pwizla Oct 23, 2024
4ea2f48
Update docusaurus/docs/dev-docs/typescript/development/guides/documen…
pwizla Oct 23, 2024
3a92d21
Update docusaurus/docs/dev-docs/typescript/development/guides/documen…
pwizla Oct 23, 2024
512e1fb
Update docusaurus/docs/dev-docs/typescript/development/guides/documen…
pwizla Oct 23, 2024
2813ffc
Update docusaurus/docs/dev-docs/typescript/development/guides/documen…
pwizla Oct 23, 2024
8f0b412
Update docusaurus/sidebars.js
pwizla Oct 23, 2024
7c434b1
Update docusaurus/docs/dev-docs/typescript/development/guides/documen…
Convly Oct 23, 2024
406a8d5
Update docusaurus/docs/dev-docs/typescript/development/guides/documen…
Convly Oct 23, 2024
619142c
Update docusaurus/docs/dev-docs/typescript/development/guides/documen…
Convly Oct 23, 2024
c0f23ce
Update docusaurus/docs/dev-docs/typescript/development.md
Convly Oct 23, 2024
b26d5ce
Update docusaurus/docs/dev-docs/typescript/development.md
Convly Oct 23, 2024
b77060c
add summaries and fixes
innerdvations Nov 6, 2024
42e6e3f
remove link to api reference
innerdvations Nov 6, 2024
38faf6d
Update docusaurus/docs/dev-docs/typescript/development.md
innerdvations Nov 6, 2024
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea/
49 changes: 25 additions & 24 deletions docusaurus/docs/dev-docs/typescript/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,27 @@
title: TypeScript development
description: Learn more about TypeScript usage with Strapi 5
tags:
- strapi() factory
- strapi.compile() function
- typescript
- plugins development

- strapi() factory
- strapi.compile() function
- typescript
- plugins development
- api
- guides
---

import NotV5 from '/docs/snippets/_not-updated-to-v5.md'
# TypeScript Development with Strapi

This page provides a comprehensive guide to developing with TypeScript in Strapi v5, covering key patterns and configurations for integrating TypeScript effectively. You'll find sections on using Strapi’s provided types, generating and managing typings for content types, configuring Strapi programmatically, and building plugins with TypeScript. Each section includes practical steps and example code to help you set up and troubleshoot TypeScript-based workflows in your Strapi project.

# TypeScript Development with Strapi
:::strapi API reference
We are preparing an API reference page, which will include an exhaustive list of the types exported by Strapi. Please come back soon! 👀
:::

<NotV5/>
## :books: Guides

While developing a [TypeScript](/dev-docs/typescript)-based application with Strapi, you can:
The guides are a curated list of common examples in which you might need to use Strapi types in your application.

- access [typings for the `Strapi`](#use-strapi-typescript-typings) class with autocompletion,
- [generate typings](#generate-typings-for-content-types-schemas) for your project's content-types,
- [start Strapi programmatically](#start-strapi-programmatically),
- and follow some TypeScript-specific instructions for [plugins development](#develop-a-plugin-using-typescript).
You can find the list of available guides [here](/dev-docs/typescript/development/guides).

## Use `Strapi` TypeScript typings

Expand All @@ -31,15 +33,15 @@ To experience TypeScript-based autocomplete while developing Strapi applications
1. Open the `./src/index.ts` file from your code editor.
2. Declare the `strapi` argument as type `Strapi` within the global `register` method:

```typescript title="./src/index.ts"
import { Strapi } from '@strapi/strapi';
```typescript title="./src/index.ts"
import type { Core } from '@strapi/strapi';

export default {
register({ strapi }: { strapi: Strapi }) {
// ...
},
};
```
export default {
register({ strapi }: { strapi: Core.Strapi }) {
// ...
},
};
```

3. Within the body of the `register` method, start typing `strapi.` and use keyboard arrows to browse the available properties.

Expand Down Expand Up @@ -116,10 +118,9 @@ To start Strapi programmatically in a TypeScript project the Strapi instance req
Strapi can be run programmatically by using the `strapi.createStrapi()` factory. Since the code of TypeScript projects is compiled in a specific directory, the parameter `distDir` should be passed to the factory to indicate where the compiled code should be read:

```js title="./server.js"

const strapi = require('@strapi/strapi');
const app = strapi.createStrapi({ distDir: './dist' });
app.start();
app.start();
```

### Use the `strapi.compile()` function
Expand All @@ -129,7 +130,7 @@ The `strapi.compile()` function should be mostly used for developing tools that
```js
const strapi = require('@strapi/strapi');

strapi.compile().then(appContext => strapi(appContext).start());
strapi.compile().then((appContext) => strapi(appContext).start());
```

## Develop a plugin using TypeScript
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: TypeScript - API Reference
sidebar_label: API Reference
description: API Reference for Strapi Type System
tags:
- typescript
- api
---

# API Reference
Copy link
Collaborator

@pwizla pwizla Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Until this page has some more content, I'd suggest we don't link to it from the sidebar and the TypeScript intro. page.

If you want to inform users that an API reference is in the works, I'd suggest you use the special :::strapi callout in the TypeScript development intro. page.

See my comment in the TypeScript development file :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, just taking over here while @Convly is off and don't fully understand what we would need to change. Could you update it the way you think would work best?


:building_construction: **Still under construction, come back later** :construction:
18 changes: 18 additions & 0 deletions docusaurus/docs/dev-docs/typescript/development/guides.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: TypeScript - Guides
sidebar_label: Guides
description: List of TypeScript guides to get started with Strapi and TypeScript
tags:
- typescript
- guides
---

# TypeScript Guides

This page includes a curated list of common examples useful to use types while [developing a Strapi TypeScript application](/dev-docs/typescript/development).

<CustomDocCardsWrapper>

<CustomDocCard emoji="📄" title="Manipulating Data" description="Manipulate documents and components in a type-safe manner." link="/dev-docs/typescript/development/guides/documents-and-entries"/>

</CustomDocCardsWrapper>
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
---
title: TypeScript - Manipulating Documents and Entries
sidebar_label: Manipulating Documents and Entries
description: TypeScript guide to get started with manipulating documents and entries
tags:
- typescript
- guides
- data
- document
- component
- uid
- entries
---

# Manipulating documents and entries

This guide will explore 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](/dev-docs/quick-start) to get started.
- **TypeScript:** Ensure TypeScript is set up in your Strapi project. You can follow Strapi's [official guide](/dev-docs/typescript#getting-started-with-typescript-in-strapi) on configuring TypeScript.
- **Generated Types:** Application types [have been generated](/dev-docs/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
import type { UID } from '@strapi/strapi';
```

- `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
import type { Data } from '@strapi/strapi';
```

- `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](/dev-docs/typescript/development#generate-typings-for-content-types-schemas).
:::

## Usage

### 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

#### Entities subsets

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

```typescript
type Credentials = Data.ContentType<'api::acount.acount', '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
import type { UID } from '@strapi/strapi';

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'>
```
Loading