diff --git a/docs/docs/guides/05-type-system/02-concepts/01-schema.mdx b/docs/docs/guides/05-type-system/02-concepts/01-schema.mdx
index 115ad857ca..a5a76d78e8 100644
--- a/docs/docs/guides/05-type-system/02-concepts/01-schema.mdx
+++ b/docs/docs/guides/05-type-system/02-concepts/01-schema.mdx
@@ -67,8 +67,8 @@ For instance, a string attribute will resolve to a primitive string in an entity
### Usage
-import Tabs from '@theme/Tabs'
-import TabItem from '@theme/TabItem'
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
@@ -89,22 +89,23 @@ declare const component: Schema.Component;
declare function processAnySchema(schema: Schema.Schema): void;
-processAnySchema(schema); // ✅
+processAnySchema(schema); // ✅
processAnySchema(contentType); // ✅
processAnySchema(component); // ✅
declare function processContentTypeSchema(schema: Schema.ContentType): void;
-processContentTypeSchema(schema); // ✅
+processContentTypeSchema(schema); // ✅
processContentTypeSchema(contentType); // ✅
processContentTypeSchema(component); // ❌ Error, a component schema is not assignable to a content-type schema
declare function processComponentSchema(schema: Schema.Component): void;
-processComponentSchema(schema); // ✅
+processComponentSchema(schema); // ✅
processComponentSchema(contentType); // ❌ Error, a content-type schema is not assignable to a component schema
processComponentSchema(component); // ✅
```
+
Schema definitions exported from the `Struct` namespace defines the low level type representation of Strapi schemas.
@@ -112,6 +113,7 @@ Schema definitions exported from the `Struct` namespace defines the low level ty
:::caution
Those types can be useful when you want to validate other types against the base ones, but realistically, the public Schema types should almost always be preferred.
:::
+
```typescript
import type { Struct } from '@strapi/strapi';
@@ -121,21 +123,22 @@ declare const component: Struct.ComponentSchema;
declare function processAnySchema(schema: Struct.Schema): void;
-processAnySchema(schema); // ✅
+processAnySchema(schema); // ✅
processAnySchema(contentType); // ✅
processAnySchema(component); // ✅
declare function processContentTypeSchema(schema: Struct.ContentTypeSchema): void;
-processContentTypeSchema(schema); // ✅
+processContentTypeSchema(schema); // ✅
processContentTypeSchema(contentType); // ✅
processContentTypeSchema(component); // ❌ Error, a component schema is not assignable to a content-type schema
declare function processComponentSchema(schema: Struct.ComponentSchema): void;
-processComponentSchema(schema); // ✅
+processComponentSchema(schema); // ✅
processComponentSchema(contentType); // ❌ Error, a content-type schema is not assignable to a component schema
processComponentSchema(component); // ✅
```
+
diff --git a/docs/docs/guides/05-type-system/02-concepts/02-uid.mdx b/docs/docs/guides/05-type-system/02-concepts/02-uid.mdx
index db2692423d..6d26d1c1ee 100644
--- a/docs/docs/guides/05-type-system/02-concepts/02-uid.mdx
+++ b/docs/docs/guides/05-type-system/02-concepts/02-uid.mdx
@@ -14,7 +14,6 @@ On this page, **a resource** is considered as **anything that can be identified
This includes (but is not limited to) controllers, schema, services, policies, middlewares, etc...
:::
-
In the Type System, UIDs play a crucial role in referencing various resources (such as schema and entities) by attaching a unique identifier.
To put it simply, a UID is a unique (string) literal key used to identify, locate, or access a particular resource within the system.
@@ -26,6 +25,7 @@ This makes it the perfect tool to index type registries or to use as a type para
### Format
A UID is composed of 3 different parts:
+
1. A namespace ([link](#1-namespaces))
2. A separator ([link](#2-separators))
3. A name ([link](#3-names))
@@ -46,7 +46,7 @@ Scoped namespaces are defined by a base name, followed by a separator (`::`) and
In Strapi there are two of them:
| Name | Definition | Description |
-|--------|:-----------------:|------------------------------------------------------|
+| ------ | :---------------: | ---------------------------------------------------- |
| API | `api::` | Represent a resource present in the `` API |
| Plugin | `plugin::` | Represent a resource present in the `` plugin |
@@ -57,7 +57,7 @@ These namespaces are used as a simple prefix and define the origin of a resource
Strapi uses three of them to create UIDs
| Name | Definition | Description |
-|--------|:----------:|-------------------------------------------------------------------------------|
+| ------ | :--------: | ----------------------------------------------------------------------------- |
| Strapi | `strapi` | Represent a resource present in the core of strapi |
| Admin | `admin` | Represent a resource present in Strapi admin |
| Global | `global` | Rarely used (_e.g. policies or middlewares_), it represents a global resource |
@@ -90,7 +90,7 @@ ContentType and Component are referring to both the related schema and entity.
:::
| | ContentType | Component | Middleware | Policy | Controller | Service |
-|--------------------------|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:|
+| ------------------------ | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: |
| `api::.` | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `plugin::.` | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `.` | :x: | :white_check_mark: | :x: | :x: | :x: | :x: |
@@ -141,6 +141,7 @@ fetch('api::article.article');
fetch('admin::user');
// ^ this should return a Data.Entity<'admin::user'>
```
+
To do that, we'll need the function to be able to provide us with the current `uid` type based on usage.
```typescript
@@ -171,14 +172,15 @@ Let's add the possibility to select which fields we want to return for our entit
```typescript
import type { UID, Data, Schema } from '@strapi/types';
-declare function fetch<
- T extends UID.ContentType,
- F extends Schema.AttributeNames
->(uid: T, fields: F[]): Data.ContentType;
+declare function fetch>(
+ uid: T,
+ fields: F[]
+): Data.ContentType;
```
:::tip
You may have noticed that we're using the inferred UID type (`T`) to reference both:
+
- An entity (`Data.Entity`)
- A schema (`Schema.AttributeNames`)
diff --git a/docs/docs/guides/05-type-system/02-concepts/03-public-registry.mdx b/docs/docs/guides/05-type-system/02-concepts/03-public-registry.mdx
index 3ee780a471..572eaaadf2 100644
--- a/docs/docs/guides/05-type-system/02-concepts/03-public-registry.mdx
+++ b/docs/docs/guides/05-type-system/02-concepts/03-public-registry.mdx
@@ -9,8 +9,8 @@ tags:
toc_max_heading_level: 5
---
-import Tabs from '@theme/Tabs'
-import TabItem from '@theme/TabItem'
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
### Context
@@ -108,6 +108,7 @@ Creating a new registry is as simple as exporting an indexed interface from the
Let's declare the content-type schema registry.
It should accept:
+
- Content-type UIDs as keys
- Content-type schemas as values
@@ -130,7 +131,7 @@ We use low level types to define our index (`Internal`/`Struct`) to keep it as g
To define `UID.ContentType`, we extract every key (`Internal.Registry.Keys`) from the public content-type registry (`Public.ContentTypeSchemas`) that matches with the base definition of a content-type UID (`Internal.UID.ContentType`).
```ts title="@strapi/types/uid.ts"
-import type { Internal, Public } from '@strapi/types'
+import type { Internal, Public } from '@strapi/types';
export type ContentType = Internal.Registry.Keys<
Public.ContentTypeSchemas,
@@ -151,7 +152,7 @@ Since `UID.ContentType` (`TUID`) is [dynamically built based on actual keys](#ui
:::
```ts title="@strapi/types/schema.ts"
-import type { UID, Public } from '@strapi/types'
+import type { UID, Public } from '@strapi/types';
export type ContentType = Public.ContentTypeSchemas[TUID];
```
@@ -172,6 +173,7 @@ Remember to use dynamic type definitions (`UID`, `Data`, `Schema`) and not stati
:::info[Reminder]
Registries are **indexed**, which means that:
+
- **When augmented** (_e.g. in users' applications_), they'll return **strongly typed values** that correspond to the defined types.
- **When empty** (_e.g. in Strapi codebase_), they'll return **generic low level types** based on their index definition.
@@ -183,6 +185,7 @@ Registries are **indexed**, which means that:
const uid: UID.ContentType;
// ^ 'api::article.article' | 'admin::user'
```
+
```ts
@@ -191,6 +194,7 @@ Registries are **indexed**, which means that:
const uid: UID.ContentType;
// ^ `admin::${string}` | `api::${string}.${string}` | `plugin::${string}.${string}` | `strapi::${string}`
```
+
:::
@@ -215,7 +219,7 @@ declare module '@strapi/strapi' {
}
}
}
-````
+```
This will force every type that depends on the `Public.ContentTypeSchemas` registry to recognize `'api::article.article'` as the only valid UID and `ApiArticleArticle` the only valid schema.
@@ -235,18 +239,20 @@ The process will generate type definitions based on the user application state (
Generate the types once.
- ```shell title="my-app/"
- yarn strapi ts:generate-types
- ```
+```shell title="my-app/"
+yarn strapi ts:generate-types
+```
+
Start the application in dev mode, and generate types on every server restart.
Useful when working with the content-type builder.
- ```shell title="my-app/"
- yarn develop
- ```
+```shell title="my-app/"
+yarn develop
+```
+
@@ -277,40 +283,43 @@ declare module '@strapi/strapi' {
When coupling everything together, the end result is a TypeScript developer experience automatically adjusted to the current context.
+
-
- ```ts title="my-app/src/index.ts"
- export default () => ({
- bootstrap() {
- strapi.findOne('ap');
- // ^ TypeScript will autocomplete with "api::article.article"
+
+```ts title="my-app/src/index.ts"
+export default () => ({
+ bootstrap() {
+ strapi.findOne('ap');
+ // ^ TypeScript will autocomplete with "api::article.article"
- strapi.findOne('ad');
- // ^ TypeScript will autocomplete with "admin::user"
+ strapi.findOne('ad');
+ // ^ TypeScript will autocomplete with "admin::user"
- strapi.findOne('api::blog.blog');
- // ^ Error, TypeScript will complain
- }
- })
- ```
-
-
- ```ts title="@strapi/strapi/document-service.ts"
- import type { UID } from '@strapi/types';
-
- export const findOne(uid: TUID) {
- // ...
+ strapi.findOne('api::blog.blog');
+ // ^ Error, TypeScript will complain
}
+})
+```
+
+
+```ts title="@strapi/strapi/document-service.ts"
+import type { UID } from '@strapi/types';
- findOne('admin::foo');
- // ^ Valid, matches 'admin::${string}'
+export const findOne(uid: TUID) {
+ // ...
+}
- findOne('plugin::bar.bar');
- // ^ Valid, matches 'plugin::${string}.${string}'
+findOne('admin::foo');
+// ^ Valid, matches 'admin::${string}'
- findOne('baz');
- // ^ Error, does not correspond to any content-type UID format
- ```
-
+findOne('plugin::bar.bar');
+// ^ Valid, matches 'plugin::${string}.${string}'
+
+findOne('baz');
+// ^ Error, does not correspond to any content-type UID format
+```
+
+
+