Closed lihbr closed 2 years ago
It turns out getting this to work with TypeScript is pretty difficult. Converting input types with generics (e.g. LinkField<"foo", "fr-fr", { foo: TimestampField }>
) to a filled type is either not possible or is so complex I can't figure it out. I tried different iterations of a large converter type (Field
=> Field<"filled">
), but using the infer
declaration seems to fall apart very quickly.
Rather than have one isFilled
function, we could have multiple versions for different field types. By doing it this way, we can set up the generics per-function specific to the field type it expects.
For example, a isLinkFilled
function could look like this:
const isLinkFilled = <
TypeEnum = string,
LangEnum = string,
DataInterface extends Record<
string,
AnyRegularField | GroupField | SliceZone
> = never,
>(
field: LinkField<TypeEnum, LangEnum, DataInterface>,
): field is LinkField<TypeEnum, LangEnum, DataInterface, "filled"> => {
// logic here
};
And be used like this:
if (isLinkFilled(link)) {
link;
// FilledLinkToDocumentField<string, string, never>
// | FilledLinkToWebField
// | FilledLinkToMediaField
} else {
link;
// EmptyLinkField<"Any">
}
This function also works for types within LinkField
, like RelationField
.
We would need the following helpers:
isTitleFilled
isRichTextFilled
isImageFilled
isContentRelationshipFilled
isLinkFilled
isLinkToMediaFilled
isDateFilled
isTimestampFilled
isColorFilled
isNumberFilled
isKeyTextFilled
isSelectFilled
isBooleanFilled
(since booleans are always filled, this can probably be omitted)isEmbedFilled
isGeoPointFilled
isIntegrationFieldsFilled
(this is such an awkward name)isGroupFilled
isSliceZoneFilled
Some of these would be aliases (e.g. isColorField
contains the same logic as isKeyTextFilled
). Splitting logic like this also means unused functions can be tree-shaken.
Possible APIs:
prismicH.isColorFilled(field)
prismicH.guard.color(field)
prismicH.filled.color(field)
prismicH.isFilled.color(field)
prismicH.isColorFieldFilled(field)
Are we fine saying TitleField and RichTextField are empty when asText(field) === ""? What about RichTextField only containing an image (or embed)?
Good point, I didn't think about non-text values. I think this is sufficient to support empty Rich Text fields (and also supports Group and Slice Zone fields):
// ...
} else if (Array.isArray(field)) {
if (field.length === 1 && "text" in field[0]) {
// TitleField, RichTextField
return !!field[0].text;
} else {
// GroupField, SliceZone
return !!field.length;
}
} else if (typeof field === "object") {
// ...
🐕
TypeScript-supported version described above: https://github.com/prismicio/prismic-helpers/pull/35
Good point, was testing some minor type inferences but didn't went in depth with those tbh (maybe a great time to start writing type test here)~
For the API, I'm fine with isColorFilled()
or isFilled.color()
, maybe the latter offers better self discovery through intellisense(?)
Is isFilledColor()
more consistent with our exising API? (maybe it reads wrong haha "if this is a filled color, then...")
No hard opinion on it~
I think isFilled.color()
works well because of the discovery aspect you mentioned. It also doesn't pollute the top-level exports list with a bunch of isXFilled()
helpers.
Types of changes
Description
Adds a collection of helpers to check if a field is filled. The
isFilled
export contains a function for each field type (Rich Text, Color, Group, Slice Zone, etc.).Resolves: #33
Old PR description
Are we fine saying `TitleField` and `RichTextField` are empty when `asText(field) === ""`? What about `RichTextField` only containing an image (or embed)?Checklist: