From 672727c8cf6aa20d01ba664f44e94048c65204f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20Herbaux?= Date: Fri, 26 Apr 2024 14:46:52 +0200 Subject: [PATCH] docs(typescript): type system cheat sheet --- .../05-type-system/02-concepts/02-uid.mdx | 2 +- .../guides/05-type-system/03-cheatsheet.mdx | 255 ++++++++++++++++++ .../core/types/src/schema/attribute/base.ts | 2 +- 3 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 docs/docs/guides/05-type-system/03-cheatsheet.mdx 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 6d26d1c1ee..2d9dc1bea0 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 @@ -111,7 +111,7 @@ This namespace contains shortcuts to dynamic UID types built from the public reg :::danger The `UID` namespace is designed to be the main interface used by developers. -Do not use the `Internal.UID` namespace except if you know what you're doing (low level extends clause, isolated internal code, etc...). +Do not use the `Internal.UID` namespace unless you know what you're doing (low level extends clause, isolated internal code, etc...). ::: #### Basic Example diff --git a/docs/docs/guides/05-type-system/03-cheatsheet.mdx b/docs/docs/guides/05-type-system/03-cheatsheet.mdx new file mode 100644 index 0000000000..a9bd8c9695 --- /dev/null +++ b/docs/docs/guides/05-type-system/03-cheatsheet.mdx @@ -0,0 +1,255 @@ +--- +title: CheatSheet +tags: + - typescript + - type system + - type + - cheatsheet +toc_max_heading_level: 3 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Admonition from '@theme/Admonition'; + +### Common Use Cases + +--- + +#### Function that Returns Any Entity + +```typescript +import type { Data } from '@strapi/types'; + +function find(): Data.Entity {} +``` + +--- + +#### Using UIDs as Resource Selectors in Function Params + + + + + +:::info +Infer the UID type based on usage and allow passing it to other generic types. +::: + +```typescript +import type { Schema, UID } from '@strapi/types'; + +function getSchema(uid: TSchemaUID): Schema.Schema {} +``` + + + + + +:::info +Simpler definition than the dynamic one. +Useful when the uid type doesn't need to be re-used by other type. +::: + +```typescript +import type { Schema, UID } from '@strapi/types'; + +function getSchema(uid: UID.Schema): Schema.Schema {} +``` + + + + + +--- + +#### Loop Over Schema Attributes + +Given a schema such as: + +```typescript +import type { Schema } from '@strapi/types'; + +declare const schema: Schema.Schema; +``` + +Extract its attributes + +```typescript +const { attributes } = schema; +``` + +Then loop over them, using `attribute.type` as a discriminator to infer the correct type for each attribute type. + +```typescript +for (const attributeName in attributes) { + // attribute is Schema.Attribute.AnyAttribute + const attribute = attributes[attributeName]; + + switch (attribute.type) { + case 'string': + // attribute is Schema.Attribute.String + console.log(attribute.minLength, attribute.maxLength); + break; + case 'relation': + // attribute is Schema.Attribute.Relation + console.log(attribute.relation); + break; + } +} +``` + +--- + +#### Type Guard + +```typescript +import type { Schema } from '@strapi/types'; + +function isContentTypeSchema(schema: Schema.Schema): schema is Schema.ContentType { + return schema.modelType === 'contentType'; +} +``` + +--- + +#### Assertion Function + +```typescript +import type { Schema } from '@strapi/types'; + +function assertIsContentTypeSchema(schema: Schema.Schema): asserts schema is Schema.ContentType { + if (schema.modelType !== 'contentType') { + throw new Error('schema is not a content-type'); + } +} +``` + +--- + +### Data + +```typescript +import type { Data } from '@strapi/types'; +``` + + + + #### Represent any entity + + ```typescript + type Entity = Data.Entity; + ``` + + #### Represent a specific content-type entity + + ```typescript + type Article = Data.Entity<'api::article.article'>; + ``` + + #### Represent a specific component entity + + ```typescript + type Metadata = Data.Entity<'seo.metadata'>; + ``` + + #### Represent any content-type + + ```typescript + type Entity = Data.Entity; + ``` + + #### Only select a subset of an entity + + ```typescript + type PartialArticle = Data.Entity<'api::article.article', 'title' | 'description' | 'author'>; + ``` + + + + #### Represent any content-type entity + + ```typescript + type ContentTypeEntity = Data.ContentType; + ``` + + #### Represent a specific content-type entity + + ```typescript + type Article = Data.ContentType<'api::article.article'>; + ``` + + #### Only select a subset of a content-type entity + + ```typescript + type PartialArticle = Data.ContentType<'api::article.article', 'title' | 'description' | 'author'>; + ``` + + + + #### Represent any component entity + + ```typescript + type ComponentEntity = Data.Component; + ``` + + #### Represent a specific component entity + + ```typescript + type Metadata = Data.Component<'seo.metadata'>; + ``` + + #### Only select a subset of a component entity + + ```typescript + type PartialMetadata = Data.Component<'seo.metadata', 'description' | 'tags'>; + ``` + + + + +--- + +### UID + +```typescript +import type { UID } from '@strapi/types'; +``` + +#### Represent any schema UID + +```typescript +type SchemaUID = UID.Schema; +``` + +#### Represent a specific content-type UID + +```typescript +const articleUID = 'api::article.article' satisfies UID.ContentType; +``` + +#### Represent a specific component entity + +```typescript +const metadataUID = 'seo.metadata' satisfies UID.Component; +``` + +#### Represent any content-type + +```typescript +type ContentTypeUID = UID.ContentType; +``` + +```typescript +declare const contentTypeUID: UID.ContentType; +``` + +#### Check if a given UID is a ContentType UID + +```typescript +type IsContentType = UID.IsContentType<'api::article.article'>; +``` + +:::note +`IsContentType` will either be `true` or `false`. +::: diff --git a/packages/core/types/src/schema/attribute/base.ts b/packages/core/types/src/schema/attribute/base.ts index f61a63f4dd..cc14033f68 100644 --- a/packages/core/types/src/schema/attribute/base.ts +++ b/packages/core/types/src/schema/attribute/base.ts @@ -75,7 +75,7 @@ export interface Attribute { * * @example * ```typescript - * import type { Schema } from '@strapi/utils'; + * import type { Schema } from '@strapi/types'; * * // An attribute of type 'boolean' * type BooleanAttribute = Schema.Attribute.OfType<'boolean'>;