diff --git a/lib/handlers/index.js b/lib/handlers/index.js
index ff572dc..1a081da 100644
--- a/lib/handlers/index.js
+++ b/lib/handlers/index.js
@@ -24,6 +24,8 @@ import {thematicBreak} from './thematic-break.js'
 
 /**
  * Default handlers for nodes.
+ *
+ * @satisfies {import('../state.js').Handlers}
  */
 export const handlers = {
   blockquote,
@@ -42,6 +44,7 @@ export const handlers = {
   listItem,
   list,
   paragraph,
+  // @ts-expect-error: root is different, but hard to type.
   root,
   strong,
   table,
diff --git a/lib/handlers/table-row.js b/lib/handlers/table-row.js
index 3796b23..5c2f0e1 100644
--- a/lib/handlers/table-row.js
+++ b/lib/handlers/table-row.js
@@ -27,6 +27,7 @@ export function tableRow(state, node, parent) {
   // Generate a body row when without parent.
   const rowIndex = siblings ? siblings.indexOf(node) : 1
   const tagName = rowIndex === 0 ? 'th' : 'td'
+  // To do: option to use `style`?
   const align = parent && parent.type === 'table' ? parent.align : undefined
   const length = align ? align.length : node.children.length
   let cellIndex = -1
diff --git a/lib/state.js b/lib/state.js
index bce9ea2..1c92ec5 100644
--- a/lib/state.js
+++ b/lib/state.js
@@ -27,7 +27,7 @@
  * @returns {Array<HastElementContent> | HastElementContent | undefined}
  *   hast node.
  *
- * @typedef {Record<string, Handler>} Handlers
+ * @typedef {Partial<Record<MdastNodes['type'], Handler>>} Handlers
  *   Handle nodes.
  *
  * @typedef Options
@@ -135,7 +135,7 @@
  *   pass different properties with the `footnoteLabelProperties` option.
  * @property {Handlers | null | undefined} [handlers]
  *   Extra handlers for nodes (optional).
- * @property {Array<string> | null | undefined} [passThrough]
+ * @property {Array<MdastNodes['type']> | null | undefined} [passThrough]
  *   List of custom mdast node types to pass through (keep) in hast (note that
  *   the node itself is passed, but eventual children are transformed)
  *   (optional).
@@ -243,9 +243,10 @@ export function createState(tree, options) {
    */
   function one(node, parent) {
     const type = node.type
+    const handle = state.handlers[type]
 
-    if (own.call(state.handlers, type)) {
-      return state.handlers[type](state, node, parent)
+    if (own.call(state.handlers, type) && handle) {
+      return handle(state, node, parent)
     }
 
     if (state.options.passThrough && state.options.passThrough.includes(type)) {
diff --git a/readme.md b/readme.md
index ad10bb2..91b5d8b 100644
--- a/readme.md
+++ b/readme.md
@@ -337,7 +337,7 @@ Handle nodes (TypeScript).
 ###### Type
 
 ```ts
-type Handlers = Record<string, Handler>
+type Handlers = Partial<Record<Nodes['type'], Handler>>
 ```
 
 ### `Options`
@@ -372,7 +372,7 @@ Configuration (TypeScript).
     — tag name to use for the footnote label
 *   `handlers` ([`Handlers`][api-handlers], optional)
     — extra handlers for nodes
-*   `passThrough` (`Array<string>`, optional)
+*   `passThrough` (`Array<Nodes['type']>`, optional)
     — list of custom mdast node types to pass through (keep) in hast (note that
     the node itself is passed, but eventual children are transformed)
 *   `unknownHandler` ([`Handler`][api-handler], optional)
diff --git a/test/core.js b/test/core.js
index 776011f..c75226a 100644
--- a/test/core.js
+++ b/test/core.js
@@ -1,7 +1,6 @@
 /**
  * @typedef {import('hast').Element} Element
  * @typedef {import('mdast').Paragraph} Paragraph
- * @typedef {import('mdast').Nodes} Nodes
  */
 
 import assert from 'node:assert/strict'