Slate types custom document models through editor value generics. Define the
element and text shapes for your editor, create a Value from the element
union, then pass that value to createEditor<Value>() or
useSlateEditor<Value>() when React owns the editor lifetime.
Defining Element And Text Types
import { type ElementOf, type TextOf, type ValueOf } from '@platejs/slate'
import { useSlateEditor, type ReactEditor } from '@platejs/slate-react'
type CustomText = { text: string; bold?: true }
type ParagraphElement = {
type: 'paragraph'
children: CustomText[]
}
type HeadingElement = {
type: 'heading'
level: number
children: CustomText[]
}
type CustomValue = (ParagraphElement | HeadingElement)[]
type CustomEditor = ReactEditor<CustomValue>
const useCustomEditor = () => {
const editor = useSlateEditor<CustomValue>()
type CustomElement = ElementOf<typeof editor>
type EditorText = TextOf<typeof editor>
type EditorValue = ValueOf<typeof editor>
return editor
}import { type ElementOf, type TextOf, type ValueOf } from '@platejs/slate'
import { useSlateEditor, type ReactEditor } from '@platejs/slate-react'
type CustomText = { text: string; bold?: true }
type ParagraphElement = {
type: 'paragraph'
children: CustomText[]
}
type HeadingElement = {
type: 'heading'
level: number
children: CustomText[]
}
type CustomValue = (ParagraphElement | HeadingElement)[]
type CustomEditor = ReactEditor<CustomValue>
const useCustomEditor = () => {
const editor = useSlateEditor<CustomValue>()
type CustomElement = ElementOf<typeof editor>
type EditorText = TextOf<typeof editor>
type EditorValue = ValueOf<typeof editor>
return editor
}Annotating Initial Values
Annotate the editor's initial value with your value type.
import { Editable, Slate, useSlateEditor } from '@platejs/slate-react'
type CustomText = { text: string; bold?: true }
type ParagraphElement = { type: 'paragraph'; children: CustomText[] }
type CustomValue = ParagraphElement[]
const initialValue: CustomValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
]
const App = () => {
const editor = useSlateEditor<CustomValue>({ initialValue })
return (
<Slate editor={editor}>
<Editable />
</Slate>
)
}import { Editable, Slate, useSlateEditor } from '@platejs/slate-react'
type CustomText = { text: string; bold?: true }
type ParagraphElement = { type: 'paragraph'; children: CustomText[] }
type CustomValue = ParagraphElement[]
const initialValue: CustomValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
]
const App = () => {
const editor = useSlateEditor<CustomValue>({ initialValue })
return (
<Slate editor={editor}>
<Editable />
</Slate>
)
}Working With Nodes
Use exported helper types to derive the document types from an editor instead of duplicating unions at every call site.
import type { ElementOf, TextOf, ValueOf } from '@platejs/slate'
type CustomElement = ElementOf<typeof editor>
type CustomText = TextOf<typeof editor>
type CustomValue = ValueOf<typeof editor>import type { ElementOf, TextOf, ValueOf } from '@platejs/slate'
type CustomElement = ElementOf<typeof editor>
type CustomText = TextOf<typeof editor>
type CustomValue = ValueOf<typeof editor>When reading a generic Node, narrow it before accessing element-specific
properties.
import { ElementApi, type Node } from '@platejs/slate'
const isParagraph = (node: Node) =>
ElementApi.isElement(node) && node.type === 'paragraph'import { ElementApi, type Node } from '@platejs/slate'
const isParagraph = (node: Node) =>
ElementApi.isElement(node) && node.type === 'paragraph'Multiple Document Models
Use a different Value type for each editor model.
const articleEditor = createEditor<ArticleValue>()
const commentEditor = createEditor<CommentValue>()const articleEditor = createEditor<ArticleValue>()
const commentEditor = createEditor<CommentValue>()Each editor carries its value through ValueOf<typeof editor>,
ElementOf<typeof editor>, and TextOf<typeof editor>.