from getpass import getuser
 from threading import Thread
 from typing import (Any, Callable, Collection, Generic, Iterable, Iterator,
-                    NamedTuple, Optional, Self, Set, TypeVar)
+                    Optional, Self, Set, TypeVar)
 from uuid import uuid4
 # ourselves
 from ircplom.events import (
     def into_endnode_updates(self, path: tuple[str, ...]
                              ) -> list[tuple[tuple[str, ...], Any]]:
         'Return path-value pairs for any update-worthy sub-elements.'
-        if isinstance(self, _CompletableStringsCollection):
+        if isinstance(self, _Completable):
             return ([(path, self._completed)] if self._completed is not None
                     else [])
-        if isinstance(self, _CompletableTopic):
-            return [(path, Topic(*self._completed))]
         updates = []
         for key, val in (self._dict.items() if isinstance(self, Dict)
                          else ((k, getattr(self, k))
     enabled: bool = False
 
 
-class Topic(NamedTuple):
+@dataclass
+class Topic:
     'Collects both setter and content of channel topic.'
     what: str = ''
     who: Optional[NickUserHost] = None
                                     client_id=self.client_id).kw(e=e)
 
 
-class _CompletableTopic(_Completable):
-    _what: str = ''
-    _who: Optional[NickUserHost] = None
-
-    def __init__(self) -> None:
-        self._completed: tuple[str, Optional[NickUserHost]] = ('', None)
-
-    @property
-    def what(self) -> str:
-        'Content of topic.'
-        return self._what
-
-    @what.setter
-    def what(self, what: str) -> None:
-        self._what = what
-
-    @property
-    def who(self) -> Optional[NickUserHost]:
-        'Setter of topic.'
-        return self._who
-
-    @who.setter
-    def who(self, who: NickUserHost) -> None:
-        copy = _NickUserHost.from_str(str(who))
-        self._who = NickUserHost(copy.nick, copy.user, copy.host)
+class _CompletableTopic(_Completable, Topic):
+    _completed: Optional[Topic] = None
 
     def complete(self) -> None:
-        self._completed = (('', None) if self._who is None
-                           else (self._what, self._who))
+        assert self.who is not None
+        copy = _NickUserHost.from_str(str(self.who))
+        self._completed = Topic(self.what,
+                                NickUserHost(copy.nick, copy.user, copy.host))
 
 
 class _Channel: