diff --git a/src/types/value/contentRelationship.ts b/src/types/value/contentRelationship.ts index 18919c3a..6096cf1f 100644 --- a/src/types/value/contentRelationship.ts +++ b/src/types/value/contentRelationship.ts @@ -5,7 +5,7 @@ import type { EmptyLinkField, LinkType } from "./link" import type { SliceZone } from "./sliceZone" /** - * Field for related documents + * Single field value for related documents * * @typeParam TypeEnum - Type API ID of the document. * @typeParam LangEnum - Language API ID of the document. @@ -13,7 +13,7 @@ import type { SliceZone } from "./sliceZone" * GraphQuery of `fetchLinks`). * @typeParam State - State of the field which determines its shape. */ -export type ContentRelationshipField< +export type SingleContentRelationshipField< TypeEnum = string, LangEnum = string, DataInterface extends @@ -24,6 +24,49 @@ export type ContentRelationshipField< ? EmptyLinkField : FilledContentRelationshipField +/** + * Repeatable field value for related documents + * + * @typeParam TypeEnum - Type API ID of the document. + * @typeParam LangEnum - Language API ID of the document. + * @typeParam DataInterface - Data fields for the document (filled in via + * GraphQuery of `fetchLinks`). + * @typeParam State - State of the field which determines its shape. + */ +export type RepeatableContentRelationshipField< + TypeEnum = string, + LangEnum = string, + DataInterface extends + | Record + | unknown = unknown, + State extends FieldState = FieldState, +> = State extends "empty" + ? [] + : [ + SingleContentRelationshipField, + ...SingleContentRelationshipField[], + ] + +/** + * Field for related documents + * + * @typeParam TypeEnum - Type API ID of the document. + * @typeParam LangEnum - Language API ID of the document. + * @typeParam DataInterface - Data fields for the document (filled in via + * GraphQuery of `fetchLinks`). + * @typeParam State - State of the field which determines its shape. + */ +export type ContentRelationshipField< + TypeEnum = string, + LangEnum = string, + DataInterface extends + | Record + | unknown = unknown, + State extends FieldState = FieldState, +> = + | SingleContentRelationshipField + | RepeatableContentRelationshipField + /** * Links that refer to documents */ diff --git a/src/types/value/link.ts b/src/types/value/link.ts index 870004b1..b46b269a 100644 --- a/src/types/value/link.ts +++ b/src/types/value/link.ts @@ -1,8 +1,8 @@ import type { AnyRegularField, FieldState } from "./types" -import type { ContentRelationshipField } from "./contentRelationship" +import type { SingleContentRelationshipField } from "./contentRelationship" import type { GroupField } from "./group" -import type { LinkToMediaField } from "./linkToMedia" +import type { SingleLinkToMediaField } from "./linkToMedia" import type { SliceZone } from "./sliceZone" /** @@ -38,7 +38,7 @@ export interface FilledLinkToWebField { } /** - * A link field. + * A single link field value. * * @typeParam TypeEnum - Type API ID of the document. * @typeParam LangEnum - Language API ID of the document. @@ -46,7 +46,7 @@ export interface FilledLinkToWebField { * GraphQuery of `fetchLinks`). * @typeParam State - State of the field which determines its shape. */ -export type LinkField< +export type SingleLinkField< TypeEnum = string, LangEnum = string, DataInterface extends @@ -56,6 +56,49 @@ export type LinkField< > = State extends "empty" ? EmptyLinkField : - | ContentRelationshipField + | SingleContentRelationshipField | FilledLinkToWebField - | LinkToMediaField + | SingleLinkToMediaField + +/** + * A repeatable link field value. + * + * @typeParam TypeEnum - Type API ID of the document. + * @typeParam LangEnum - Language API ID of the document. + * @typeParam DataInterface - Data fields for the document (filled in via + * GraphQuery of `fetchLinks`). + * @typeParam State - State of the field which determines its shape. + */ +export type RepeatableLinkFieldValue< + TypeEnum = string, + LangEnum = string, + DataInterface extends + | Record + | unknown = unknown, + State extends FieldState = FieldState, +> = State extends "empty" + ? [] + : [ + SingleLinkField, + ...SingleLinkField[], + ] + +/** + * A link field. + * + * @typeParam TypeEnum - Type API ID of the document. + * @typeParam LangEnum - Language API ID of the document. + * @typeParam DataInterface - Data fields for the document (filled in via + * GraphQuery of `fetchLinks`). + * @typeParam State - State of the field which determines its shape. + */ +export type LinkField< + TypeEnum = string, + LangEnum = string, + DataInterface extends + | Record + | unknown = unknown, + State extends FieldState = FieldState, +> = + | SingleLinkField + | RepeatableLinkFieldValue diff --git a/src/types/value/linkToMedia.ts b/src/types/value/linkToMedia.ts index 85d1a92c..a626467e 100644 --- a/src/types/value/linkToMedia.ts +++ b/src/types/value/linkToMedia.ts @@ -3,15 +3,34 @@ import type { FieldState } from "./types" import type { EmptyLinkField, LinkType } from "./link" /** - * A link field that points to media. + * A single link field value that points to media. * * @typeParam State - State of the field which determines its shape. */ -export type LinkToMediaField = +export type SingleLinkToMediaField = State extends "empty" ? EmptyLinkField : FilledLinkToMediaField +/** + * Repeatable link field values that point to media. + * + * @typeParam State - State of the field which determines its shape. + */ +export type RepeatableLinkToMediaField = + State extends "empty" + ? [] + : [SingleLinkToMediaField, ...SingleLinkToMediaField[]] + +/** + * A link field that points to media. + * + * @typeParam State - State of the field which determines its shape. + */ +export type LinkToMediaField = + | SingleLinkToMediaField + | RepeatableLinkToMediaField + /** * A link that points to media. */ diff --git a/test/types/fields-contentRelationship.types.ts b/test/types/fields-contentRelationship.types.ts index 71f455f3..0c02d215 100644 --- a/test/types/fields-contentRelationship.types.ts +++ b/test/types/fields-contentRelationship.types.ts @@ -19,7 +19,7 @@ import * as prismic from "../../src" } /** - * Filled state. + * Filled state (non-repeatable). */ expectType({ link_type: prismic.LinkType.Document, @@ -63,7 +63,57 @@ expectType>({ }) /** - * Empty state. + * Filled state (repeatable). + */ +expectType([ + { + link_type: prismic.LinkType.Document, + id: "string", + uid: "string", + type: "string", + tags: ["string"], + lang: "string", + url: "string", + slug: "string", + isBroken: true, + data: undefined, + text: "string", + }, +]) +expectType>([ + { + link_type: prismic.LinkType.Document, + id: "string", + uid: "string", + type: "string", + tags: ["string"], + lang: "string", + url: "string", + slug: "string", + isBroken: true, + data: undefined, + text: "string", + }, +]) +expectType>([ + // @ts-expect-error - Empty repeatable fields cannot contain a value. + { + link_type: prismic.LinkType.Document, + id: "string", + uid: "string", + type: "string", + tags: ["string"], + lang: "string", + url: "string", + slug: "string", + isBroken: true, + data: undefined, + text: "string", + }, +]) + +/** + * Empty state (non-repeatable). */ expectType({ link_type: prismic.LinkType.Document, @@ -79,7 +129,23 @@ expectType>( ) /** - * Empty state with text. + * Empty state (repeatable). + */ +expectType([ + { + link_type: prismic.LinkType.Document, + }, +]) +expectType>([]) +expectType>([ + // @ts-expect-error - Empty fields cannot contain a value. + { + link_type: prismic.LinkType.Document, + }, +]) + +/** + * Empty state with text (only non-repeatable). */ expectType({ link_type: prismic.LinkType.Document, @@ -98,7 +164,23 @@ expectType>( ) /** - * Supports custom document type. + * Empty state with text (repeatable). + */ +expectType([ + { + link_type: prismic.LinkType.Document, + text: "string", + }, +]) +expectType>([ + { + link_type: prismic.LinkType.Document, + text: "string", + }, +]) + +/** + * Supports custom document type (non-repeatable). */ expectType>({ link_type: prismic.LinkType.Document, @@ -107,17 +189,42 @@ expectType>({ tags: [], lang: "string", }) -expectType>({ - link_type: prismic.LinkType.Document, - id: "string", +expectType>( // @ts-expect-error - Document type must match the given type. - type: "string", - tags: [], - lang: "string", -}) + { + link_type: prismic.LinkType.Document, + id: "string", + type: "string", + tags: [], + lang: "string", + }, +) /** - * Supports custom document language. + * Supports custom document type (repeatable). + */ +expectType>([ + { + link_type: prismic.LinkType.Document, + id: "string", + type: "foo", + tags: [], + lang: "string", + }, +]) +expectType>([ + { + link_type: prismic.LinkType.Document, + id: "string", + // @ts-expect-error - Document type must match the given type. + type: "string", + tags: [], + lang: "string", + }, +]) + +/** + * Supports custom document language (non-repeatable). */ expectType>({ link_type: prismic.LinkType.Document, @@ -126,17 +233,40 @@ expectType>({ tags: [], lang: "fr-fr", }) +// @ts-expect-error - Document language must match the given type. expectType>({ link_type: prismic.LinkType.Document, id: "string", type: "string", tags: [], - // @ts-expect-error - Document language must match the given type. lang: "string", }) /** - * Supports custom document data. + * Supports custom document language (repeatable). + */ +expectType>([ + { + link_type: prismic.LinkType.Document, + id: "string", + type: "string", + tags: [], + lang: "fr-fr", + }, +]) +expectType>([ + { + link_type: prismic.LinkType.Document, + id: "string", + type: "string", + tags: [], + // @ts-expect-error - Document language must match the given type. + lang: "string", + }, +]) + +/** + * Supports custom document data (non-repeatable). */ expectType< prismic.ContentRelationshipField< @@ -156,3 +286,27 @@ expectType< bar: false, }, }) + +/** + * Supports custom document data (repeatable). + */ +expectType< + prismic.ContentRelationshipField< + string, + string, + { foo: prismic.BooleanField } + > +>([ + { + link_type: prismic.LinkType.Document, + id: "string", + type: "string", + tags: [], + lang: "fr-fr", + data: { + foo: true, + // @ts-expect-error - Only given fields are valid. + bar: false, + }, + }, +]) diff --git a/test/types/fields-link.types.ts b/test/types/fields-link.types.ts index 2f8a3a5d..c0042df9 100644 --- a/test/types/fields-link.types.ts +++ b/test/types/fields-link.types.ts @@ -36,14 +36,26 @@ expectType( /** * Filled state. */ -// Web link + +// Web link (non-repeatable) expectType({ link_type: prismic.LinkType.Web, url: "string", target: "string", text: "string", }) -// Content relationship link + +// Web link (repeatable) +expectType([ + { + link_type: prismic.LinkType.Web, + url: "string", + target: "string", + text: "string", + }, +]) + +// Content relationship link (non-repeatable) expectType({ link_type: prismic.LinkType.Document, id: "string", @@ -57,7 +69,25 @@ expectType({ data: undefined, text: "string", }) -// Media link + +// Content relationship link (repeatable) +expectType([ + { + link_type: prismic.LinkType.Document, + id: "string", + uid: "string", + type: "string", + tags: ["string"], + lang: "string", + url: "string", + slug: "string", + isBroken: true, + data: undefined, + text: "string", + }, +]) + +// Media link (non-repeatable) expectType({ link_type: prismic.LinkType.Media, name: "string", @@ -82,8 +112,31 @@ expectType>({ text: "string", }) +// Media link (repeatable) +expectType([ + { + link_type: prismic.LinkType.Media, + name: "string", + kind: "string", + url: "string", + size: "string", + height: "string", + width: "string", + text: "string", + }, +]) +expectType>([ + { + link_type: prismic.LinkType.Web, + url: "string", + target: "string", + text: "string", + }, +]) +expectType>([]) + /** - * Empty state. + * Empty state (non-repeatable). */ expectType({ link_type: prismic.LinkType.Any, @@ -121,7 +174,23 @@ expectType>( ) /** - * Empty state with text. + * Empty state (repeatable). + */ +expectType([ + { + link_type: prismic.LinkType.Any, + }, +]) +expectType>([]) +expectType>([ + // @ts-expect-error - Empty fields cannot contain a value. + { + link_type: prismic.LinkType.Web, + }, +]) + +/** + * Empty state with text (non-repeatable). */ expectType>({ link_type: prismic.LinkType.Web, @@ -167,7 +236,36 @@ expectType>({ }) /** - * Supports custom document type for document links. + * Empty state with text (repeatable). + */ +expectType>([ + { + link_type: prismic.LinkType.Web, + text: "string", + }, + { + link_type: prismic.LinkType.Document, + text: "string", + }, + { + link_type: prismic.LinkType.Media, + text: "string", + }, + { + link_type: prismic.LinkType.Any, + text: "string", + }, +]) +expectType>([ + // @ts-expect-error - Empty fields cannot contain a value. + { + link_type: prismic.LinkType.Web, + text: "string", + }, +]) + +/** + * Supports custom document type for document links (non-repeatable). */ expectType>({ link_type: prismic.LinkType.Document, @@ -186,7 +284,30 @@ expectType>({ }) /** - * Supports custom document language for document links. + * Supports custom document type for document links (repeatable). + */ +expectType>([ + { + link_type: prismic.LinkType.Document, + id: "string", + type: "foo", + tags: [], + lang: "string", + }, +]) +expectType>([ + // @ts-expect-error - Document type must match the given type. + { + link_type: prismic.LinkType.Document, + id: "string", + type: "string", + tags: [], + lang: "string", + }, +]) + +/** + * Supports custom document language for document links (non-repeatable). */ expectType>({ link_type: prismic.LinkType.Document, @@ -205,7 +326,30 @@ expectType>({ }) /** - * Supports custom document data for document links. + * Supports custom document language for document links (repeatable). + */ +expectType>([ + { + link_type: prismic.LinkType.Document, + id: "string", + type: "string", + tags: [], + lang: "fr-fr", + }, +]) +expectType>([ + // @ts-expect-error - Document language must match the given type. + { + link_type: prismic.LinkType.Document, + id: "string", + type: "string", + tags: [], + lang: "string", + }, +]) + +/** + * Supports custom document data for document links (non-repeatable). */ expectType>({ link_type: prismic.LinkType.Document, @@ -219,3 +363,60 @@ expectType>({ bar: false, }, }) + +/** + * Supports custom document data for document links (repeatable). + */ +expectType>([ + { + link_type: prismic.LinkType.Document, + id: "string", + type: "string", + tags: [], + lang: "fr-fr", + data: { + foo: true, + // @ts-expect-error - Only given fields are valid. + bar: false, + }, + }, +]) + +/** + * Supports multiple link types (repeatable). + */ +expectType([ + { + link_type: prismic.LinkType.Web, + url: "string", + target: "string", + text: "string", + }, + { + link_type: prismic.LinkType.Document, + id: "string", + uid: "string", + type: "string", + tags: ["string"], + lang: "string", + url: "string", + slug: "string", + isBroken: true, + data: undefined, + text: "string", + }, + { + link_type: prismic.LinkType.Media, + name: "string", + kind: "string", + url: "string", + size: "string", + height: "string", + width: "string", + text: "string", + }, + { + link_type: prismic.LinkType.Web, + text: "string", + }, +]) diff --git a/test/types/fields-linkToMedia.types.ts b/test/types/fields-linkToMedia.types.ts index c5b63fbf..7e19c4fe 100644 --- a/test/types/fields-linkToMedia.types.ts +++ b/test/types/fields-linkToMedia.types.ts @@ -19,7 +19,7 @@ import * as prismic from "../../src" } /** - * Filled state. + * Filled state (non-repeatable). */ expectType({ id: "string", @@ -57,7 +57,51 @@ expectType>({ }) /** - * Empty state. + * Filled state (repeatable). + */ +expectType([ + { + id: "string", + link_type: prismic.LinkType.Media, + name: "string", + kind: "string", + url: "string", + size: "string", + height: "string", + width: "string", + text: "string", + }, +]) +expectType>([ + { + id: "string", + link_type: prismic.LinkType.Media, + name: "string", + kind: "string", + url: "string", + size: "string", + height: "string", + width: "string", + text: "string", + }, +]) +expectType>([ + // @ts-expect-error - Empty repeatable fields cannot contain a value. + { + link_type: prismic.LinkType.Media, + id: "string", + name: "string", + kind: "string", + url: "string", + size: "string", + height: "string", + width: "string", + text: "string", + }, +]) + +/** + * Empty state (non-repeatable). */ expectType({ link_type: prismic.LinkType.Media, @@ -73,7 +117,23 @@ expectType>( ) /** - * Empty state with text. + * Empty state (repeatable). + */ +expectType([ + { + link_type: prismic.LinkType.Media, + }, +]) +expectType>([]) +expectType>([ + // @ts-expect-error - Empty repeatable fields cannot contain a value. + { + link_type: prismic.LinkType.Media, + }, +]) + +/** + * Empty state with text (non-repeatable). */ expectType({ link_type: prismic.LinkType.Media, @@ -90,3 +150,19 @@ expectType>( text: "string", }, ) + +/** + * Empty state with text (repeatable). + */ +expectType([ + { + link_type: prismic.LinkType.Media, + text: "string", + }, +]) +expectType>([ + { + link_type: prismic.LinkType.Media, + text: "string", + }, +])