@sanity/types
Version:
Type definitions for common Sanity data structures
71 lines (66 loc) • 2.13 kB
text/typescript
import {type PortableTextObject, type PortableTextSpan, type PortableTextTextBlock} from './types'
function isRecord(value: unknown): value is Record<string, unknown> {
return !!value && (typeof value == 'object' || typeof value == 'function')
}
/**
* Assert that a given object is a portable-text text-block type object
*
* @remarks
* * The `markDefs` and `style` property of a block is optional.
* * Block types can be named, so expect anything of the _type property.
*
* @alpha
*/
export function isPortableTextTextBlock<T = PortableTextSpan | PortableTextObject>(
value: unknown,
): value is PortableTextTextBlock<T> {
return (
isRecord(value) &&
typeof value._type === 'string' && // block types can be named, so expect anything here.
Array.isArray(value.children) &&
value.children.every((child) => isRecord(child)) &&
('markDefs' in value // optional property
? Array.isArray(value.markDefs) && value.markDefs.every((def) => isRecord(def))
: true) &&
('style' in value ? typeof value.style === 'string' : true) // optional property
)
}
/**
* Assert that a given object is a portable-text span-type object
*
* @remarks
* The `marks` property of a block is optional.
*
* @alpha
*/
export function isPortableTextSpan(value: unknown): value is PortableTextSpan {
return (
isRecord(value) &&
value._type === 'span' &&
typeof value.text === 'string' &&
('marks' in value // optional property
? Array.isArray(value.marks) && value.marks.every((mark) => typeof mark === 'string')
: true)
)
}
/**
* Assert that a given object is a portable-text list-text-block-type object
*
* @remarks
* Uses `isPortableTextTextBlock` and checks for `listItem` and `level`
*
* @see isPortableTextTextBlock
*
* @alpha
*/
export function isPortableTextListBlock<T = PortableTextSpan | PortableTextObject>(
value: unknown,
): value is PortableTextTextBlock<T> {
return (
isPortableTextTextBlock(value) &&
'listItem' in value &&
typeof value.listItem === 'string' &&
'level' in value &&
Number.isInteger(value.level)
)
}