diff --git a/lib/private/Authentication/Listeners/LoginFailedListener.php b/lib/private/Authentication/Listeners/LoginFailedListener.php
index 72800ad509cfd74c93ef456885e97cbef1557ed0..19f0b92c3a64705edccf42defaf903c52e369a1c 100644
--- a/lib/private/Authentication/Listeners/LoginFailedListener.php
+++ b/lib/private/Authentication/Listeners/LoginFailedListener.php
@@ -35,6 +35,9 @@ use OCP\EventDispatcher\IEventListener;
 use OCP\IUserManager;
 use OCP\Util;
 
+/**
+ * @template-implements IEventListener<\OC\Authentication\Events\LoginFailed>
+ */
 class LoginFailedListener implements IEventListener {
 
 	/** @var IEventDispatcher */
diff --git a/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php b/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php
index b841f81555b0912dd6c015a56e8989b0ec1dba81..55009c317c46410de85569f6054776eab5b834f8 100644
--- a/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php
+++ b/lib/private/Authentication/Listeners/RemoteWipeActivityListener.php
@@ -35,6 +35,9 @@ use OCP\EventDispatcher\Event;
 use OCP\EventDispatcher\IEventListener;
 use Psr\Log\LoggerInterface;
 
+/**
+ * @template-implements IEventListener<\OC\Authentication\Events\ARemoteWipeEvent>
+ */
 class RemoteWipeActivityListener implements IEventListener {
 
 	/** @var IActvityManager */
diff --git a/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php b/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php
index 52698855bd59976e13c189ec84acdc0534aa68dd..9ba2717c97368c2fd5aae49bad696e35c715e641 100644
--- a/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php
+++ b/lib/private/Authentication/Listeners/RemoteWipeEmailListener.php
@@ -40,6 +40,9 @@ use OCP\Mail\IMessage;
 use Psr\Log\LoggerInterface;
 use function substr;
 
+/**
+ * @template-implements IEventListener<\OC\Authentication\Events\ARemoteWipeEvent>
+ */
 class RemoteWipeEmailListener implements IEventListener {
 
 	/** @var IMailer */
diff --git a/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php b/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php
index 831107a05cd397d1e9141601e9bd9385e777cd05..965fb291fbf568a782c181dd9e994bc6facc7295 100644
--- a/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php
+++ b/lib/private/Authentication/Listeners/RemoteWipeNotificationsListener.php
@@ -35,6 +35,9 @@ use OCP\EventDispatcher\Event;
 use OCP\EventDispatcher\IEventListener;
 use OCP\Notification\IManager as INotificationManager;
 
+/**
+ * @template-implements IEventListener<\OC\Authentication\Events\ARemoteWipeEvent>
+ */
 class RemoteWipeNotificationsListener implements IEventListener {
 
 	/** @var INotificationManager */
diff --git a/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php b/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php
index c8f2da82db65f820bd068e129148e8e5265a4fa8..057568f514e2e1b4c9f782de485fd1640ab5ec8c 100644
--- a/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php
+++ b/lib/private/Authentication/Listeners/UserDeletedStoreCleanupListener.php
@@ -31,6 +31,9 @@ use OCP\EventDispatcher\Event;
 use OCP\EventDispatcher\IEventListener;
 use OCP\User\Events\UserDeletedEvent;
 
+/**
+ * @template-implements IEventListener<\OCP\User\Events\UserDeletedEvent>
+ */
 class UserDeletedStoreCleanupListener implements IEventListener {
 
 	/** @var Registry */
diff --git a/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php b/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php
index e1199814da5fd89638082ec339fa452acf1c0da9..bb3a522556fce59b8c6fc8b5c99e4296848f3c7a 100644
--- a/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php
+++ b/lib/private/Authentication/Listeners/UserDeletedTokenCleanupListener.php
@@ -33,6 +33,9 @@ use OCP\User\Events\UserDeletedEvent;
 use Psr\Log\LoggerInterface;
 use Throwable;
 
+/**
+ * @template-implements IEventListener<\OCP\User\Events\UserDeletedEvent>
+ */
 class UserDeletedTokenCleanupListener implements IEventListener {
 
 	/** @var Manager */
diff --git a/lib/private/Authentication/Listeners/UserLoggedInListener.php b/lib/private/Authentication/Listeners/UserLoggedInListener.php
index f3ab833734d96377cd87eaf8e1d80ebd18a537cc..9d90f09b2962673cad850b60af4caf7f10f2c257 100644
--- a/lib/private/Authentication/Listeners/UserLoggedInListener.php
+++ b/lib/private/Authentication/Listeners/UserLoggedInListener.php
@@ -31,6 +31,9 @@ use OCP\EventDispatcher\Event;
 use OCP\EventDispatcher\IEventListener;
 use OCP\User\Events\PostLoginEvent;
 
+/**
+ * @template-implements IEventListener<\OCP\User\Events\PostLoginEvent>
+ */
 class UserLoggedInListener implements IEventListener {
 
 	/** @var Manager */
diff --git a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
index b164fda5e62390b3b8331d92c44043b366f5f407..aaf5ef00bfaf7c446314df247cd490acb41a2637 100644
--- a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
+++ b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
@@ -113,10 +113,11 @@ interface IRegistrationContext {
 	 *
 	 * This is equivalent to calling IEventDispatcher::addServiceListener
 	 *
+	 * @template T of \OCP\EventDispatcher\Event
 	 * @param string $event preferably the fully-qualified class name of the Event sub class to listen for
-	 * @psalm-param string|class-string<\OCP\EventDispatcher\Event> $event preferably the fully-qualified class name of the Event sub class to listen for
+	 * @psalm-param string|class-string<T> $event preferably the fully-qualified class name of the Event sub class to listen for
 	 * @param string $listener fully qualified class name (or ::class notation) of a \OCP\EventDispatcher\IEventListener that can be built by the DI container
-	 * @psalm-param class-string<\OCP\EventDispatcher\IEventListener> $listener fully qualified class name that can be built by the DI container
+	 * @psalm-param class-string<\OCP\EventDispatcher\IEventListener<T>> $listener fully qualified class name that can be built by the DI container
 	 * @param int $priority
 	 *
 	 * @see IEventDispatcher::addServiceListener()
diff --git a/lib/public/EventDispatcher/IEventDispatcher.php b/lib/public/EventDispatcher/IEventDispatcher.php
index 997834ad7b5c56963a78996368783a9b309752b5..471447e4b9f819b1d5ffa5613e41684caf5621f5 100644
--- a/lib/public/EventDispatcher/IEventDispatcher.php
+++ b/lib/public/EventDispatcher/IEventDispatcher.php
@@ -35,7 +35,9 @@ namespace OCP\EventDispatcher;
 interface IEventDispatcher {
 
 	/**
+	 * @template T of \OCP\EventDispatcher\Event
 	 * @param string $eventName preferably the fully-qualified class name of the Event sub class
+	 * @psalm-param string|class-string<T> $eventName preferably the fully-qualified class name of the Event sub class
 	 * @param callable $listener the object that is invoked when a matching event is dispatched
 	 * @param int $priority
 	 *
@@ -44,7 +46,9 @@ interface IEventDispatcher {
 	public function addListener(string $eventName, callable $listener, int $priority = 0): void;
 
 	/**
+	 * @template T of \OCP\EventDispatcher\Event
 	 * @param string $eventName preferably the fully-qualified class name of the Event sub class
+	 * @psalm-param string|class-string<T> $eventName preferably the fully-qualified class name of the Event sub class
 	 * @param callable $listener the object that is invoked when a matching event is dispatched
 	 *
 	 * @since 19.0.0
@@ -52,8 +56,11 @@ interface IEventDispatcher {
 	public function removeListener(string $eventName, callable $listener): void;
 
 	/**
+	 * @template T of \OCP\EventDispatcher\Event
 	 * @param string $eventName preferably the fully-qualified class name of the Event sub class to listen for
+	 * @psalm-param string|class-string<T> $eventName preferably the fully-qualified class name of the Event sub class to listen for
 	 * @param string $className fully qualified class name (or ::class notation) of a \OCP\EventDispatcher\IEventListener that can be built by the DI container
+	 * @psalm-param class-string<\OCP\EventDispatcher\IEventListener<T>> $className fully qualified class name that can be built by the DI container
 	 * @param int $priority
 	 *
 	 * @since 17.0.0
@@ -61,8 +68,11 @@ interface IEventDispatcher {
 	public function addServiceListener(string $eventName, string $className, int $priority = 0): void;
 
 	/**
+	 * @template T of \OCP\EventDispatcher\Event
 	 * @param string $eventName
+	 * @psalm-param string|class-string<T> $eventName
 	 * @param Event $event
+	 * @psalm-param T $event
 	 *
 	 * @since 17.0.0
 	 */
diff --git a/lib/public/EventDispatcher/IEventListener.php b/lib/public/EventDispatcher/IEventListener.php
index 25906fa798ecabd4c88024113319e354ad02b77a..fcf44133aff707478be42792a68d415d845727dd 100644
--- a/lib/public/EventDispatcher/IEventListener.php
+++ b/lib/public/EventDispatcher/IEventListener.php
@@ -28,11 +28,14 @@ namespace OCP\EventDispatcher;
 
 /**
  * @since 17.0.0
+ *
+ * @template T of Event
  */
 interface IEventListener {
 
 	/**
 	 * @param Event $event
+	 * @psalm-param T $event
 	 *
 	 * @since 17.0.0
 	 */