diff --git a/utils_maintenance/c_sort_blocks.py b/utils_maintenance/c_sort_blocks.py
index ba06bd076d2e8c87fa4e8476996947b8fc1dc4f5..bc3f318a3b65ccf0b63abe83b5ce511db835f0ee 100755
--- a/utils_maintenance/c_sort_blocks.py
+++ b/utils_maintenance/c_sort_blocks.py
@@ -26,6 +26,10 @@ sys.path.append(os.path.join(PWD, "modules"))
 
 from batch_edit_text import run
 
+from typing import (
+    Optional,
+)
+
 SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(PWD, "..", "..", ".."))))
 
 # TODO, move to config file
@@ -42,7 +46,7 @@ SOURCE_EXT = (
 )
 
 
-def sort_struct_lists(fn, data_src):
+def sort_struct_lists(fn: str, data_src: str) -> Optional[str]:
     import re
 
     # eg:
@@ -63,7 +67,7 @@ def sort_struct_lists(fn, data_src):
 
     lines = data_src.splitlines(keepends=True)
 
-    def can_sort(l):
+    def can_sort(l: str) -> Optional[int]:
         if re_match_struct.match(l):
             return 1
         if re_match_struct_type.match(l):
@@ -94,6 +98,7 @@ def sort_struct_lists(fn, data_src):
     data_dst = "".join(lines)
     if data_src != data_dst:
         return data_dst
+    return None
 
 
 run(
diff --git a/utils_maintenance/c_struct_clean.py b/utils_maintenance/c_struct_clean.py
index e327ad867c7a7ba14130605da79a0db9c203630e..7fe60594a11734521813357bdfc28e1e8aa0ca4a 100755
--- a/utils_maintenance/c_struct_clean.py
+++ b/utils_maintenance/c_struct_clean.py
@@ -29,6 +29,11 @@ import os
 import sys
 import re
 
+from typing import (
+    Dict,
+    Optional,
+)
+
 PWD = os.path.dirname(__file__)
 sys.path.append(os.path.join(PWD, "modules"))
 
@@ -52,12 +57,12 @@ SOURCE_EXT = (
 re_words = re.compile("[A-Za-z_][A-Za-z_0-9]*")
 re_match_struct = re.compile(r"struct\s+([A-Za-z_][A-Za-z_0-9]*)\s*;")
 
-def clean_structs(fn, data_src):
+def clean_structs(fn: str, data_src: str) -> Optional[str]:
     import re
 
-    word_occurance = {}
-    for w in re_words.finditer(data_src):
-        w = w.group(0)
+    word_occurance: Dict[str, int] = {}
+    for w_match in re_words.finditer(data_src):
+        w = w_match.group(0)
         try:
             word_occurance[w] += 1
         except KeyError:
@@ -80,6 +85,7 @@ def clean_structs(fn, data_src):
     data_dst = "".join(lines)
     if data_src != data_dst:
         return data_dst
+    return None
 
 run(
     directories=[os.path.join(SOURCE_DIR, d) for d in SOURCE_DIRS],
diff --git a/utils_maintenance/cmake_sort_filelists.py b/utils_maintenance/cmake_sort_filelists.py
index 6ee34c22230aa9e3208661f4df93a6edb695b319..7ca5565bc6a314794b0089fa4f5c4b706973dc15 100755
--- a/utils_maintenance/cmake_sort_filelists.py
+++ b/utils_maintenance/cmake_sort_filelists.py
@@ -27,6 +27,10 @@ Sorts CMake path lists
 import os
 import sys
 
+from typing import (
+    Optional,
+)
+
 PWD = os.path.dirname(__file__)
 sys.path.append(os.path.join(PWD, "modules"))
 
@@ -47,11 +51,11 @@ SOURCE_EXT = (
     ".m", ".mm",
 )
 
-def sort_cmake_file_lists(fn, data_src):
+def sort_cmake_file_lists(fn: str, data_src: str) -> Optional[str]:
     fn_dir = os.path.dirname(fn)
     lines = data_src.splitlines(keepends=True)
 
-    def can_sort(l):
+    def can_sort(l: str) -> bool:
         l = l.split("#", 1)[0].strip()
         # Source files.
         if l.endswith(SOURCE_EXT):
@@ -63,8 +67,9 @@ def sort_cmake_file_lists(fn, data_src):
         # Libs.
         if l.startswith(("bf_", "extern_")) and "." not in l and "/" not in l:
             return True
+        return False
 
-    def can_sort_compat(a, b):
+    def can_sort_compat(a: str, b: str) -> bool:
         # Strip comments.
         a = a.split("#", 1)[0]
         b = b.split("#", 1)[0]
@@ -74,14 +79,14 @@ def sort_cmake_file_lists(fn, data_src):
             # return False
 
             # Compare loading paths.
-            a = a.split("/")
-            b = b.split("/")
-            if len(a) == 1 and len(b) == 1:
+            a_ls = a.split("/")
+            b_ls = b.split("/")
+            if len(a_ls) == 1 and len(b_ls) == 1:
                 return True
-            if len(a) == len(b):
-                if len(a) == 1:
+            if len(a_ls) == len(b_ls):
+                if len(a_ls) == 1:
                     return True
-                if a[:-1] == b[:-1]:
+                if a_ls[:-1] == b_ls[:-1]:
                     return True
         return False
 
@@ -103,6 +108,7 @@ def sort_cmake_file_lists(fn, data_src):
     data_dst = "".join(lines)
     if data_src != data_dst:
         return data_dst
+    return None
 
 
 run(
diff --git a/utils_maintenance/modules/batch_edit_text.py b/utils_maintenance/modules/batch_edit_text.py
index 2e63df89b96b1d932e592ab4abe647fec22081e5..381a2d9f2644a055c116e3b54294d86bb1deeeb3 100644
--- a/utils_maintenance/modules/batch_edit_text.py
+++ b/utils_maintenance/modules/batch_edit_text.py
@@ -16,7 +16,22 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
-def operation_wrap(args):
+from typing import (
+    Callable,
+    Generator,
+    Optional,
+    Sequence,
+    Tuple,
+)
+
+TextOpFn = Callable[
+    # file_name, data_src
+    [str, str],
+    # data_dst or None when no change is made.
+    Optional[str]
+]
+
+def operation_wrap(args: Tuple[str, TextOpFn]) -> None:
     fn, text_operation = args
     with open(fn, "r", encoding="utf-8") as f:
         data_src = f.read()
@@ -29,16 +44,16 @@ def operation_wrap(args):
         f.write(data_dst)
 
 def run(*,
-        directories,
-        is_text,
-        text_operation,
-        use_multiprocess,
-):
+        directories: Sequence[str],
+        is_text: Callable[[str], bool],
+        text_operation: TextOpFn,
+        use_multiprocess: bool,
+) -> None:
     print(directories)
 
     import os
 
-    def source_files(path):
+    def source_files(path: str) -> Generator[str, None, None]:
         for dirpath, dirnames, filenames in os.walk(path):
             dirnames[:] = [d for d in dirnames if not d.startswith(".")]
             for filename in filenames: