diff --git a/src/Extensions/MaintenanceLockExtension.php b/src/Extensions/MaintenanceLockExtension.php
index eec57758..c1f15802 100644
--- a/src/Extensions/MaintenanceLockExtension.php
+++ b/src/Extensions/MaintenanceLockExtension.php
@@ -12,8 +12,9 @@
  * Class MaintenanceLockExtension
  * Adds a maintenance lock UI to SiteConfig
  *
- * @property SiteConfig|$this owner
  * @package Symbiote\QueuedJobs\Extensions
+ *
+ * @extends DataExtension<SiteConfig&static>
  */
 class MaintenanceLockExtension extends DataExtension
 {
diff --git a/src/Extensions/ScheduledExecutionExtension.php b/src/Extensions/ScheduledExecutionExtension.php
index ead6cc4f..3eb0861e 100644
--- a/src/Extensions/ScheduledExecutionExtension.php
+++ b/src/Extensions/ScheduledExecutionExtension.php
@@ -10,6 +10,7 @@
 use SilverStripe\Forms\ReadonlyField;
 use SilverStripe\Forms\TextField;
 use SilverStripe\ORM\DataExtension;
+use SilverStripe\ORM\DataObject;
 use SilverStripe\ORM\FieldType\DBDatetime;
 use Symbiote\QueuedJobs\DataObjects\QueuedJobDescriptor;
 use Symbiote\QueuedJobs\Jobs\ScheduledExecutionJob;
@@ -23,7 +24,10 @@
  *
  * @author marcus@symbiote.com.au
  * @license BSD License http://silverstripe.org/bsd-license/
+ *
  * @method QueuedJobDescriptor ScheduledJob()
+ *
+ * @extends DataExtension<DataObject&static>
  */
 class ScheduledExecutionExtension extends DataExtension
 {
diff --git a/src/Services/QueuedJobService.php b/src/Services/QueuedJobService.php
index 70c89f36..69edadf7 100644
--- a/src/Services/QueuedJobService.php
+++ b/src/Services/QueuedJobService.php
@@ -402,7 +402,6 @@ public function getNextPendingJob($type = null)
             ->sort('ID', 'ASC');
 
         // see if there's any blocked jobs that need to be resumed
-        /** @var QueuedJobDescriptor $waitingJob */
         $waitingJob = $list->find('JobStatus', QueuedJob::STATUS_WAIT);
 
         if ($waitingJob) {
@@ -410,7 +409,6 @@ public function getNextPendingJob($type = null)
         }
 
         // Otherwise, lets find any 'new' jobs that are waiting to execute
-        /** @var QueuedJobDescriptor $newJob */
         $newJob = $list
             ->filter('JobStatus', QueuedJob::STATUS_NEW)
             ->where(sprintf(
@@ -468,7 +466,6 @@ public function checkJobHealth($queue = null)
                 '"Expiry" IS NULL AND "LastEdited" <= ?' => $this->getInitStateExpiry()
             ]);
 
-        /** @var QueuedJobDescriptor $stalledJob */
         foreach ($stalledJobs as $stalledJob) {
             $jobClass = $stalledJob->Implementation;
 
@@ -492,7 +489,6 @@ public function checkJobHealth($queue = null)
         // now, find those that need to be marked before the next check
         // foreach job, mark it as having been incremented
         foreach ($runningJobs as $job) {
-            /** @var QueuedJobDescriptor $job */
             $job->LastProcessedCount = $job->StepsProcessed;
             $job->write();
         }
@@ -752,7 +748,6 @@ protected function grabMutex(QueuedJobDescriptor $jobDescriptor)
                     Convert::raw2sql($descriptorId)
                 ));
 
-                /** @var QueuedJobDescriptor $updatedDescriptor */
                 $updatedDescriptor = QueuedJobDescriptor::get()->byID($descriptorId);
 
                 // If we couldn't find the descriptor or the descriptor is not the one we expect to have
@@ -800,7 +795,6 @@ public function runJob($jobId)
         $logger = $this->getLogger();
 
         // first retrieve the descriptor
-        /** @var QueuedJobDescriptor $jobDescriptor */
         $jobDescriptor = DataObject::get_by_id(
             QueuedJobDescriptor::class,
             (int)$jobId
@@ -817,7 +811,6 @@ public function runJob($jobId)
         // We need to use $_SESSION directly because SS ties the session to a controller that no longer exists at
         // this point of execution in some circumstances
         $originalUserID = isset($_SESSION['loggedInAs']) ? $_SESSION['loggedInAs'] : 0;
-        /** @var Member|null $originalUser */
         $originalUser = $originalUserID
             ? DataObject::get_by_id(Member::class, $originalUserID)
             : null;
@@ -869,7 +862,6 @@ public function runJob($jobId)
                     Subsite::changeSubsite($job->SubsiteID);
 
                     // lets set the base URL as far as Director is concerned so that our URLs are correct
-                    /** @var Subsite $subsite */
                     $subsite = DataObject::get_by_id(Subsite::class, $job->SubsiteID);
                     if ($subsite && $subsite->exists()) {
                         $domain = $subsite->domain();
@@ -882,7 +874,6 @@ public function runJob($jobId)
                 // while not finished
                 while (!$job->jobFinished() && !$broken) {
                     // see that we haven't been set to 'paused' or otherwise by another process
-                    /** @var QueuedJobDescriptor $jobDescriptor */
                     $jobDescriptor = DataObject::get_by_id(
                         QueuedJobDescriptor::class,
                         (int)$jobId
@@ -1282,7 +1273,7 @@ protected function humanReadable($size)
      *          The number of seconds to include jobs that have just finished, allowing a job list to be built that
      *          includes recently finished jobs
      *
-     * @return DataList|QueuedJobDescriptor[]
+     * @return DataList<QueuedJobDescriptor>
      */
     public function getJobList($type = null, $includeUpUntil = 0)
     {
diff --git a/src/Tasks/Engines/DoormanRunner.php b/src/Tasks/Engines/DoormanRunner.php
index baff3ca3..41981e44 100644
--- a/src/Tasks/Engines/DoormanRunner.php
+++ b/src/Tasks/Engines/DoormanRunner.php
@@ -89,7 +89,6 @@ public function runQueue($queue)
 
         // split jobs out into multiple tasks...
 
-        /** @var ProcessManager $manager */
         $manager = Injector::inst()->create(ProcessManager::class);
         $manager->setWorker(
             sprintf(