diff --git a/docs/source/api/symbolic_language/astnodes.rst b/docs/source/api/symbolic_language/astnodes.rst
index 4d5c4b89f410ba7bcbde695819eb4b7351fcd71b..ff31c98ecbb5822ef3b1fba8b18f577f2c352e0e 100644
--- a/docs/source/api/symbolic_language/astnodes.rst
+++ b/docs/source/api/symbolic_language/astnodes.rst
@@ -4,6 +4,6 @@ Kernel Structure
 
 .. automodule:: pystencils.sympyextensions.astnodes
 
-.. autoclass:: pystencils.sympyextensions.AssignmentCollection
+.. autoclass:: pystencils.AssignmentCollection
     :members:
 
diff --git a/docs/source/backend/index.rst b/docs/source/backend/index.rst
index f2fe9346dbe4d38722b69dd9c279d0eb11c98773..fb7c9c33b8e221e7f501084470ff937203e2efb6 100644
--- a/docs/source/backend/index.rst
+++ b/docs/source/backend/index.rst
@@ -13,6 +13,7 @@ who wish to customize or extend the behaviour of the code generator in their app
     ast
     iteration_space
     translation
+    typification
     platforms
     transformations
     jit
diff --git a/docs/source/backend/translation.rst b/docs/source/backend/translation.rst
index a4c7d36b58701f76e7e35283e12d01e705af1890..fb418b719fdb1d5031b24b4cc0423437cab4a7a0 100644
--- a/docs/source/backend/translation.rst
+++ b/docs/source/backend/translation.rst
@@ -13,6 +13,3 @@ Kernel Translation
 
 .. autoclass:: pystencils.backend.kernelcreation.FreezeExpressions
     :members:
-
-.. autoclass:: pystencils.backend.kernelcreation.Typifier
-    :members:
diff --git a/docs/source/backend/typification.rst b/docs/source/backend/typification.rst
new file mode 100644
index 0000000000000000000000000000000000000000..b79ee831123876d684877b0d6cc3e7a768cffda3
--- /dev/null
+++ b/docs/source/backend/typification.rst
@@ -0,0 +1,31 @@
+**********
+AST Typing
+**********
+
+In order for many transformations and code emission to function, all symbols and expressions
+occuring inside a backend syntax tree must have a valid type.
+In order to determine these types, pystencils provides an AST visitor (the `Typifier`) that attempts to
+figure those out from the expression tree's structure and a few default data types.
+
+.. autoclass:: pystencils.backend.kernelcreation.Typifier
+    :members:
+
+.. autoclass:: pystencils.backend.kernelcreation.typification.TypificationError
+    :members:
+
+Typifier Internal Classes
+=========================
+
+.. autoclass:: pystencils.backend.kernelcreation.typification.TypeContext
+    :members:
+
+.. autoclass:: pystencils.backend.kernelcreation.typification.TypeHint
+    :members:
+
+.. autoclass:: pystencils.backend.kernelcreation.typification.ToDefault
+    :members:
+
+.. autoclass:: pystencils.backend.kernelcreation.typification.DereferencableTo
+    :members:
+
+.. autodata :: pystencils.backend.kernelcreation.typification.InferenceHook
diff --git a/src/pystencils/backend/kernelcreation/typification.py b/src/pystencils/backend/kernelcreation/typification.py
index d85c5341073e548301ca74131ad091ef5db35595..1fede168a28809310d9224f1f093dbb712ce7e6b 100644
--- a/src/pystencils/backend/kernelcreation/typification.py
+++ b/src/pystencils/backend/kernelcreation/typification.py
@@ -49,7 +49,7 @@ from ..ast.expressions import (
 )
 from ..functions import PsMathFunction, CFunction
 
-__all__ = ["Typifier"]
+__all__ = ["Typifier", "TypificationError"]
 
 
 class TypificationError(Exception):
@@ -104,29 +104,43 @@ class TypeContext:
     Instances of this class are used to propagate and check data types across expression subtrees
     of the AST. Each type context has:
 
-     - A target type `target_type`, which shall be applied to all expressions it covers
-     - A set of restrictions on the target type:
-       - `require_nonconst` to make sure the target type is not `const`, as required on assignment left-hand sides
-       - Additional restrictions may be added in the future.
-
-    Each typing context needs to be resolved at some point.
-    This can happen immediately during its expansion in the following ways:
-
-     - During expansion, a node with a fixed type is encountered; then, that type is applied to the context; or
-     - A type is enforced directly from a surrounding or otherwise associated context; or
-     - the context is supplied with a type hint through `apply_hint`, which it can either use to figure out its type
-       directly, or pass on to any number of registered `InferenceHook`s;
-       one of those *must* then provide the target type.
-
-    If a type context cannot be resolved while it is being processed, its resolution needs to be deferred.
-    It must then be hooked into its surrounding (parent) context using an `InferenceHook`.
-    Through this hook, it receives two second chances for resolution:
-
-     - If the surrounding context gets resolved to a type, the type of the nested context *must* be inferred
-       from that surrounding type
-     - If the surrounding context is supplied with a type hint, that type hint is given to the inference hook
-       which then *may* use that to infer the type of its nested context;
-       it that is successful, the hook must also provide the type for the surrounding context.
+    - A target type ``target_type``, which shall be applied to all expressions it covers
+    - A set of restrictions on the target type:
+      - ``require_nonconst`` to make sure the target type is not ``const``,
+      as required on assignment left-hand sides
+      - Additional restrictions may be added in the future.
+
+    **Target type**
+    
+    Each typing context needs to be assigned its target type at some point.
+    The target type may be
+
+    - predetermined by specifying it at the context's construction, or otherwise
+    - obtained from expressions covered by the context for which a type could be inferred, or otherwise
+    - inferred from the type of the enclosing context via an inference hook, or as a last resort
+    - determined from a type hint applied to the enclosing context via an inference hook.
+
+    **Expansion** 
+    
+    Expression nodes are added to a type context using either `apply_dtype` or `infer_dtype`.
+    In both cases, the context's target type will be applied to the node,
+    unless it already has a conflicting type.
+    If no target type is set yet, `infer_dtype` stores the node as *deferred*,
+    and the target type will be retroactively applied to it once it becomes known.
+
+    **Type Hints and Inference Hooks**
+
+    If a type context could not be resolved during its expansion, its type must be inferred from information
+    about its enclosing context.
+    To this end, it must be linked to its surrounding context using an `InferenceHook`.
+    If the surrounding context already has a target type, the inference hook is called directly with that type.
+    Otherwise, it will be called later when the surrounding context receives either its target type or a type hint.
+
+    If the enclosing context is resolved to a type, the nested context *must* be resolved by the inference hook,
+    or an error must be raised.
+    If the enclosing context receives a type hint instead, the inference hook *may* infer both the target types of
+    its inner **and** its outer context. In that case, the type of the enclosing context must be returned by the hook
+    callback.
     """
 
     def __init__(
@@ -222,7 +236,7 @@ class TypeContext:
         """Infer the data type for the given expression.
 
         If the target_type of this context is already known, it will be applied to the given expression.
-        Otherwise, the expression is deferred, and a type will be applied to it as soon as `apply_type` is
+        Otherwise, the expression is deferred, and a type will be applied to it as soon as `apply_dtype` is
         called on this context.
 
         If the expression already has a data type set, it must be compatible with the target type
@@ -235,6 +249,10 @@ class TypeContext:
             self._apply_target_type(expr)
 
     def _propagate_target_type(self):
+        """Propagates the target type to any registered inference hooks and applies it to any deferred nodes.
+        
+        Call after the target type of this context has been set.
+        """
         assert self._target_type is not None
 
         for hook in self._inference_hooks:
@@ -246,6 +264,7 @@ class TypeContext:
         self._deferred_exprs = []
 
     def _apply_target_type(self, expr: PsExpression):
+        """Apply the target type to an expression node."""
         assert self._target_type is not None
 
         if expr.dtype is not None:
@@ -328,7 +347,8 @@ class TypeContext:
         else:
             return dtype == self._target_type
 
-    def _fix_constness(self, dtype: PsType, expr: PsExpression | None = None):
+    def _fix_constness(self, dtype: PsType, expr: PsExpression | None = None) -> PsType:
+        """Check and convert the constness of a type according to the ``require_nonconst`` restriction."""
         if self._require_nonconst:
             if dtype.const:
                 if expr is None:
@@ -355,8 +375,8 @@ class Typifier:
     All nodes covered by the same typing context must have the same type.
 
     Starting from an expression's root, a typing context is implicitly expanded through
-    the recursive descent into a node's children. In particular, a child is typified within
-    the same context as its parent if the node's semantics require parent and child to have
+    the recursive descent into a node's children. In particular, a type context is extended from a parent
+    to its child node if the expressions's semantics require parent and child to have
     the same type (e.g. at arithmetic operators, mathematical functions, etc.).
     If a node's child is required to have a different type, a new context is opened.
 
@@ -373,13 +393,13 @@ class Typifier:
 
     The following general rules apply:
 
-     - The context's ``default_dtype`` is applied to all untyped symbols encountered inside a right-hand side expression
-     - If an untyped symbol is encountered on an assignment's left-hand side, it will first be attempted to infer its
-       type from the right-hand side. If that fails, the context's ``default_dtype`` will be applied.
-     - It is an error if an untyped symbol occurs in the same type context as a typed symbol or constant
-       with a non-default data type.
-     - By default, all expressions receive a ``const`` type unless they occur on a (non-declaration) assignment's
-       left-hand side
+    - The context's ``default_dtype`` is applied to all untyped symbols encountered inside a right-hand side expression
+    - If an untyped symbol is encountered on an assignment's left-hand side, it will first be attempted to infer its
+      type from the right-hand side. If that fails, the context's ``default_dtype`` will be applied.
+    - It is an error if an untyped symbol occurs in the same type context as a typed symbol or constant
+      with a non-default data type.
+    - By default, all expressions receive a ``const`` type unless they occur on a (non-declaration) assignment's
+      left-hand side
 
     **Typing of symbol expressions**