docs: update code formatting and minor text adjustments in type system documentation (#20186)

This commit is contained in:
Jean-Sébastien Herbaux 2024-04-23 18:19:37 +02:00 committed by GitHub
parent bdaafbbb3c
commit 01bf5cfbe4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 55 deletions

View File

@ -67,8 +67,8 @@ For instance, a string attribute will resolve to a primitive string in an entity
### Usage ### Usage
import Tabs from '@theme/Tabs' import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem' import TabItem from '@theme/TabItem';
<Tabs> <Tabs>
<TabItem value="public" label="Public" default> <TabItem value="public" label="Public" default>
@ -105,6 +105,7 @@ processComponentSchema(schema); // ✅
processComponentSchema(contentType); // ❌ Error, a content-type schema is not assignable to a component schema processComponentSchema(contentType); // ❌ Error, a content-type schema is not assignable to a component schema
processComponentSchema(component); // ✅ processComponentSchema(component); // ✅
``` ```
</TabItem> </TabItem>
<TabItem value="internal" label="Internal"> <TabItem value="internal" label="Internal">
Schema definitions exported from the `Struct` namespace defines the low level type representation of Strapi schemas. 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 :::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. 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 ```typescript
import type { Struct } from '@strapi/strapi'; import type { Struct } from '@strapi/strapi';
@ -137,5 +139,6 @@ processComponentSchema(schema); // ✅
processComponentSchema(contentType); // ❌ Error, a content-type schema is not assignable to a component schema processComponentSchema(contentType); // ❌ Error, a content-type schema is not assignable to a component schema
processComponentSchema(component); // ✅ processComponentSchema(component); // ✅
``` ```
</TabItem> </TabItem>
</Tabs> </Tabs>

View File

@ -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... 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. 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. 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 ### Format
A UID is composed of 3 different parts: A UID is composed of 3 different parts:
1. A namespace ([link](#1-namespaces)) 1. A namespace ([link](#1-namespaces))
2. A separator ([link](#2-separators)) 2. A separator ([link](#2-separators))
3. A name ([link](#3-names)) 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: In Strapi there are two of them:
| Name | Definition | Description | | Name | Definition | Description |
|--------|:-----------------:|------------------------------------------------------| | ------ | :---------------: | ---------------------------------------------------- |
| API | `api::<scope>` | Represent a resource present in the `<scope>` API | | API | `api::<scope>` | Represent a resource present in the `<scope>` API |
| Plugin | `plugin::<scope>` | Represent a resource present in the `<scope>` plugin | | Plugin | `plugin::<scope>` | Represent a resource present in the `<scope>` 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 Strapi uses three of them to create UIDs
| Name | Definition | Description | | Name | Definition | Description |
|--------|:----------:|-------------------------------------------------------------------------------| | ------ | :--------: | ----------------------------------------------------------------------------- |
| Strapi | `strapi` | Represent a resource present in the core of strapi | | Strapi | `strapi` | Represent a resource present in the core of strapi |
| Admin | `admin` | Represent a resource present in Strapi admin | | Admin | `admin` | Represent a resource present in Strapi admin |
| Global | `global` | Rarely used (_e.g. policies or middlewares_), it represents a global resource | | 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 | | | ContentType | Component | Middleware | Policy | Controller | Service |
|--------------------------|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:| | ------------------------ | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: |
| `api::<scope>.<name>` | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | `api::<scope>.<name>` | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `plugin::<scope>.<name>` | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | `plugin::<scope>.<name>` | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `<category>.<name>` | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | | `<category>.<name>` | :x: | :white_check_mark: | :x: | :x: | :x: | :x: |
@ -141,6 +141,7 @@ fetch('api::article.article');
fetch('admin::user'); fetch('admin::user');
// ^ this should return a Data.Entity<'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. To do that, we'll need the function to be able to provide us with the current `uid` type based on usage.
```typescript ```typescript
@ -171,14 +172,15 @@ Let's add the possibility to select which fields we want to return for our entit
```typescript ```typescript
import type { UID, Data, Schema } from '@strapi/types'; import type { UID, Data, Schema } from '@strapi/types';
declare function fetch< declare function fetch<T extends UID.ContentType, F extends Schema.AttributeNames<T>>(
T extends UID.ContentType, uid: T,
F extends Schema.AttributeNames<T> fields: F[]
>(uid: T, fields: F[]): Data.ContentType<T>; ): Data.ContentType<T>;
``` ```
:::tip :::tip
You may have noticed that we're using the inferred UID type (`T`) to reference both: You may have noticed that we're using the inferred UID type (`T`) to reference both:
- An entity (`Data.Entity<T>`) - An entity (`Data.Entity<T>`)
- A schema (`Schema.AttributeNames<T>`) - A schema (`Schema.AttributeNames<T>`)

View File

@ -9,8 +9,8 @@ tags:
toc_max_heading_level: 5 toc_max_heading_level: 5
--- ---
import Tabs from '@theme/Tabs' import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem' import TabItem from '@theme/TabItem';
### Context ### 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. Let's declare the content-type schema registry.
It should accept: It should accept:
- Content-type UIDs as keys - Content-type UIDs as keys
- Content-type schemas as values - 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`). 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" ```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< export type ContentType = Internal.Registry.Keys<
Public.ContentTypeSchemas, Public.ContentTypeSchemas,
@ -151,7 +152,7 @@ Since `UID.ContentType` (`TUID`) is [dynamically built based on actual keys](#ui
::: :::
```ts title="@strapi/types/schema.ts" ```ts title="@strapi/types/schema.ts"
import type { UID, Public } from '@strapi/types' import type { UID, Public } from '@strapi/types';
export type ContentType<TUID extends UID.ContentType> = Public.ContentTypeSchemas[TUID]; export type ContentType<TUID extends UID.ContentType> = Public.ContentTypeSchemas[TUID];
``` ```
@ -172,6 +173,7 @@ Remember to use dynamic type definitions (`UID`, `Data`, `Schema`) and not stati
:::info[Reminder] :::info[Reminder]
Registries are **indexed**, which means that: 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 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. - **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; const uid: UID.ContentType;
// ^ 'api::article.article' | 'admin::user' // ^ 'api::article.article' | 'admin::user'
``` ```
</TabItem> </TabItem>
<TabItem value="empty" label="Empty"> <TabItem value="empty" label="Empty">
```ts ```ts
@ -191,6 +194,7 @@ Registries are **indexed**, which means that:
const uid: UID.ContentType; const uid: UID.ContentType;
// ^ `admin::${string}` | `api::${string}.${string}` | `plugin::${string}.${string}` | `strapi::${string}` // ^ `admin::${string}` | `api::${string}.${string}` | `plugin::${string}.${string}` | `strapi::${string}`
``` ```
</TabItem> </TabItem>
</Tabs> </Tabs>
::: :::
@ -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. 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.
@ -238,6 +242,7 @@ The process will generate type definitions based on the user application state (
```shell title="my-app/" ```shell title="my-app/"
yarn strapi ts:generate-types yarn strapi ts:generate-types
``` ```
</TabItem> </TabItem>
<TabItem value="dev" label="During Development"> <TabItem value="dev" label="During Development">
Start the application in dev mode, and generate types on every server restart. Start the application in dev mode, and generate types on every server restart.
@ -247,6 +252,7 @@ The process will generate type definitions based on the user application state (
```shell title="my-app/" ```shell title="my-app/"
yarn develop yarn develop
``` ```
</TabItem> </TabItem>
</Tabs> </Tabs>
@ -277,6 +283,7 @@ declare module '@strapi/strapi' {
When coupling everything together, the end result is a TypeScript developer experience automatically adjusted to the current context. When coupling everything together, the end result is a TypeScript developer experience automatically adjusted to the current context.
<!-- prettier-ignore-start -->
<Tabs> <Tabs>
<TabItem value="app" label="User Application"> <TabItem value="app" label="User Application">
@ -314,3 +321,5 @@ When coupling everything together, the end result is a TypeScript developer expe
``` ```
</TabItem> </TabItem>
</Tabs> </Tabs>
<!-- prettier-ignore-end -->