@datocms/cma-client
Version:
JS client for DatoCMS REST Content Management API
66 lines (65 loc) • 2.71 kB
TypeScript
/**
* Narrows a union of block shapes to the member whose model (`item_type`)
* matches `Id`.
*
* Any object carrying `relationships.item_type.data.id` is narrowable —
* that covers blocks returned from `nested: true` responses as well as the
* object variants of request payloads (updated / newly-created blocks). The
* bare string IDs that may appear inside request payloads (to reference
* existing, unchanged blocks) are filtered out of the result.
*/
export type NarrowBlockByItemType<T, Id extends string> = Extract<T, {
relationships: {
item_type: {
data: {
type: 'item_type';
id: Id;
};
};
};
}>;
/**
* Type guard that narrows a block to a specific model.
*
* Two call styles, same narrowing behavior:
*
* - Curried: `isBlockOfType(itemTypeId)` returns a predicate, ideal for
* `Array#filter` / `Array#find`.
* - Direct: `isBlockOfType(itemTypeId, block)` checks a single value inline,
* handy inside `if` statements when you already have the block in hand.
*
* The ID generic is inferred from the first argument, so no explicit type
* parameter is needed. Given any input type `T`, the result narrows to
* `Extract<T, { relationships: { item_type: { data: { id: Id } } } }>`,
* which covers:
*
* - `ItemInNestedResponse<D>` (responses with `nested: true`)
* - `ItemCreateSchema<D>` / `ItemUpdateSchema<D>` (request payloads, object
* variants; plain string IDs are filtered out — there's no way to narrow
* them without an external lookup)
*
* The default (non-nested) response shape, where block fields are arrays of
* plain string IDs, is deliberately not supported — the type information is
* not recoverable from an ID alone.
*
* For the literal `Id` to be preserved (and narrowing to work), the argument
* must be typed as a literal — use `as const` on pre-set ID constants.
*
* @example
* ```ts
* const SESSION_BLOCK_ID = 'abc123' as const;
*
* const record = await client.items.find<Schema.ConferenceDay>(id, { nested: true });
*
* // Curried — predicate for filter/find
* const sessions = record.agenda.filter(isBlockOfType(SESSION_BLOCK_ID));
* sessions[0].attributes.signup_url; // OK — narrowed
*
* // Direct — inline check on a single block
* if (isBlockOfType(SESSION_BLOCK_ID, record.agenda[0])) {
* record.agenda[0].attributes.signup_url; // OK — narrowed
* }
* ```
*/
export declare function isBlockOfType<Id extends string>(itemTypeId: Id): <T>(block: T) => block is NarrowBlockByItemType<T, Id>;
export declare function isBlockOfType<T, Id extends string>(itemTypeId: Id, block: T): block is NarrowBlockByItemType<T, Id>;