title: Python typing: typed dictionary or defaultdict extending classes
body: <p>I have an old piece of python code that parses a rigorously formatted text file (storing strings for localisation). Because the structure is hierarchical and some elements may or may not be present, the programme uses nested <code>defaultdict</code>s to represent it. Something like:</p>
  
  <pre><code>terms = defaultdict(lambda: defaultdict(str)) # dict&lt;key, dict&lt;lang, translation&gt;&gt;
  </code></pre>
  
  <p>Because these dictionaries are not typed (as in their members can be any type) and because they are nested, and because I need to add another level to that hierarchy, I decided to add typing to this programme:</p>
  
  <pre><code>from typing import Tuple, Dict, Set, List, NewType
  
  Key = NewType('Key', str)
  Lang = NewType('Lang', str)
  Translation = NewType('Translation', str)
  PLIndex = NewType('PLIndex', int)
  </code></pre>
  
  <p>However, I can't for the life of me figure out how to rewrite the <code>terms =</code> line above to make those nested <code>defaultdict</code>s typed. </p>
  
  <p>What I ended up doing is just basically wrapping <code>dict</code> into my types, which doesn't look too good:</p>
  
  <pre><code>class Forms:
      def __init__(self):
          self.dct: Dict[PLIndex, Translation] = {}
  
      def __getitem__(self, item: PLIndex) -&gt; Translation:
          return self.dct[item]
  
      def __setitem__(self, key: PLIndex, value: Translation) -&gt; None:
          self.dct[key] = value
  
  
  class Translations:
      def __init__(self):
          self.dct: Dict[Lang, Forms] = {}
  
      def __getitem__(self, item: Lang) -&gt; Forms:
          if item not in self.dct:
              self.dct[item] = Forms()
          return self.dct[item]
  
      def __setitem__(self, key: Lang, value: Forms) -&gt; None:
          self.dct[key] = value
  
      def items(self):
          return self.dct.items()
  
  
  class Terms:
      def __init__(self):
          self.dct: Dict[Key, Translations] = {}
  
      def __getitem__(self, item: Key) -&gt; Translations:
          if item not in self.dct:
              self.dct[item] = Translations()
          return self.dct[item]
  
      def __setitem__(self, key: Key, value: Translations) -&gt; None:
          self.dct[key] = value
  
      def __len__(self):
          return len(self.dct)
  
      def items(self):
          return self.dct.items()
  
  ...
  
  terms = Terms()
  </code></pre>
  
  <p>Is there a way I could declare my <code>Forms</code>, <code>Translations</code> and other types as just <code>NewType</code>s for <code>dict</code>/<code>defaultdict</code> and be able to rewrite the <code>terms =</code> in a way that would enforce correct types for the nested dictionaries? Or could I extend <code>dict</code>/<code>defaultdict</code> (instead of wrapping them) and be able to enforce correct types? Or is there a better way altogether?</p>