Skip to content

Commit

Permalink
fix: allow generics with link variant (#374)
Browse files Browse the repository at this point in the history
Co-authored-by: lihbr <[email protected]>
  • Loading branch information
lihbr and lihbr authored Jan 16, 2025
1 parent 5429a3f commit 7cff55e
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 19 deletions.
35 changes: 22 additions & 13 deletions src/types/value/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const LinkType = {
* @typeParam DataInterface - Data fields for the document (filled via the
* `fetchLinks` or `graphQuery` query parameter).
* @typeParam State - State of the field which determines its shape.
* @typeParam Variant - Variants of the link.
*/
export type LinkField<
TypeEnum = string,
Expand All @@ -31,9 +32,10 @@ export type LinkField<
| Record<string, AnyRegularField | GroupField | SliceZone>
| unknown = unknown,
State extends FieldState = FieldState,
Variant = string,
> = State extends "empty"
? EmptyLinkField
: FilledLinkField<TypeEnum, LangEnum, DataInterface>
? EmptyLinkField<typeof LinkType.Any, Variant>
: FilledLinkField<TypeEnum, LangEnum, DataInterface, Variant>

/**
* A link field that is filled.
Expand All @@ -42,52 +44,59 @@ export type LinkField<
* @typeParam LangEnum - Language API ID of the document.
* @typeParam DataInterface - Data fields for the document (filled via the
* `fetchLinks` or `graphQuery` query parameter).
* @typeParam Variant - Variants of the link.
*/
export type FilledLinkField<
TypeEnum = string,
LangEnum = string,
DataInterface extends
| Record<string, AnyRegularField | GroupField | SliceZone>
| unknown = unknown,
> = (
| FilledContentRelationshipField<TypeEnum, LangEnum, DataInterface>
| FilledLinkToMediaField
| FilledLinkToWebField
) &
OptionalLinkProperties
Variant = string,
> =
| (FilledContentRelationshipField<TypeEnum, LangEnum, DataInterface> &
OptionalLinkProperties<Variant>)
| FilledLinkToMediaField<Variant>
| FilledLinkToWebField<Variant>

/**
* A link field that is not filled.
*
* @typeParam _Unused - THIS PARAMETER IS NOT USED. If you are passing a type,
* **please remove it**.
* @typeParam Variant - Variants of the link.
*/
export type EmptyLinkField<
_Unused extends
(typeof LinkType)[keyof typeof LinkType] = typeof LinkType.Any,
Variant = string,
> = {
link_type: "Any"
} & OptionalLinkProperties
} & OptionalLinkProperties<Variant>

/**
* A link field pointing to a relative or absolute URL.
*
* @typeParam Variant - Variants of the link.
*/
export type FilledLinkToWebField = {
export type FilledLinkToWebField<Variant = string> = {
link_type: "Web"
url: string
target?: string
} & OptionalLinkProperties
} & OptionalLinkProperties<Variant>

/**
* Optional properties available to link fields. It is used to augment existing
* link-like fields (like content relationship fields) with field-specific
* properties.
*
* @typeParam Variant - Variants of the link.
*
* @internal
*/
// Remember to update the `getOptionalLinkProperties()` function when updating
// this type. The function should check for every property.
export type OptionalLinkProperties = {
export type OptionalLinkProperties<Variant = string> = {
text?: string
variant?: string
variant?: Variant
}
19 changes: 13 additions & 6 deletions src/types/value/linkToMedia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,25 @@ import type { OptionalLinkProperties } from "./link"
* A link field that points to media.
*
* @typeParam State - State of the field which determines its shape.
* @typeParam Variant - Variants of the link.
*/
export type LinkToMediaField<State extends FieldState = FieldState> =
State extends "empty" ? EmptyLinkToMediaField : FilledLinkToMediaField
export type LinkToMediaField<
State extends FieldState = FieldState,
Variant = string,
> = State extends "empty"
? EmptyLinkToMediaField<Variant>
: FilledLinkToMediaField<Variant>

type EmptyLinkToMediaField = {
type EmptyLinkToMediaField<Variant = string> = {
link_type: "Any"
} & OptionalLinkProperties
} & OptionalLinkProperties<Variant>

/**
* A link that points to media.
*
* @typeParam Variant - Variants of the link.
*/
export type FilledLinkToMediaField = {
export type FilledLinkToMediaField<Variant = string> = {
id: string
link_type: "Media"
name: string
Expand All @@ -26,4 +33,4 @@ export type FilledLinkToMediaField = {
size: string
height?: string | null
width?: string | null
} & OptionalLinkProperties
} & OptionalLinkProperties<Variant>
82 changes: 82 additions & 0 deletions test/types/fields-link.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,88 @@ expectType<prismic.LinkField<string, string, never, "empty">>({
link_type: prismic.LinkType.Any,
variant: "string",
})
expectType<prismic.LinkField<string, string, never, "empty", "foo" | "bar">>({
link_type: prismic.LinkType.Any,
variant: "foo",
})
expectType<prismic.LinkField<string, string, never, "empty", "foo" | "bar">>({
link_type: prismic.LinkType.Any,
// @ts-expect-error - Variant must match the given enum.
variant: "string",
})

/**
* Filled state with explicit variant.
*/
expectType<prismic.LinkField<string, string, never, "filled", "foo" | "bar">>({
link_type: prismic.LinkType.Web,
url: "string",
target: "string",
text: "string",
variant: "foo",
})
expectType<prismic.LinkField<string, string, never, "filled", "foo" | "bar">>({
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",
variant: "foo",
})
expectType<prismic.LinkField<string, string, never, "filled", "foo" | "bar">>({
link_type: prismic.LinkType.Media,
id: "string",
name: "string",
kind: "string",
url: "string",
size: "string",
height: "string",
width: "string",
text: "string",
variant: "foo",
})
expectType<prismic.LinkField<string, string, never, "filled", "foo" | "bar">>({
link_type: prismic.LinkType.Web,
url: "string",
target: "string",
text: "string",
// @ts-expect-error - Variant must match the given enum.
variant: "string",
})
expectType<prismic.LinkField<string, string, never, "filled", "foo" | "bar">>({
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",
// @ts-expect-error - Variant must match the given enum.
variant: "string",
})
expectType<prismic.LinkField<string, string, never, "filled", "foo" | "bar">>({
link_type: prismic.LinkType.Media,
id: "string",
name: "string",
kind: "string",
url: "string",
size: "string",
height: "string",
width: "string",
text: "string",
// @ts-expect-error - Variant must match the given enum.
variant: "string",
})

/**
* Supports custom document type for document links.
Expand Down

0 comments on commit 7cff55e

Please sign in to comment.