TypedDict: Mark a set of keys as incompatible

123 Views Asked by At

I have an interface named Foo which is supposed to have, aside from other common keys, either one of the two given keys, bar and baz. To let PyCharm know, I wrote two interfaces:

from typing import TypedDict

class Foo1(TypedDict):
  bar: str
    
class Foo2(TypedDict):
  baz: int

Foo = Foo1 | Foo2

foo_instance_1: Foo = {  # Works fine
  'bar': 'foobar'
}
foo_instance_2: Foo = {  # Also fine
  'baz': 42
}

foo_instance_3: Foo = {  # Warning: Expected type 'Foo1 | Foo2', got 'dict[str, str | int]' instead
  'bar': 'foobar',
  'baz': 42
}

That works. However, the problem is the real interface I'm dealing with has more than just one incompatible set of keys. That being said, if there are three sets with 2, 3 and 4 keys correspondingly, I'll have to write 2 * 3 * 4 or 24 interfaces. It would be great if something like this exists:

class Foo(TypedDict):
  bar: IncompatibleWith('baz', 'qux')[str]
  baz: IncompatibleWith('bar', 'qux')[int]
  qux: IncompatibleWith('bar', 'baz')[bool]

...or, better yet:

@incompatible('bar', 'baz', 'qux')
# ...
class Foo(TypedDict):
  bar: str
  baz: int
  qux: bool

Real world context: I'm writing a source code generator to generate API interfaces for a site, which I do not have control of, in Python (that site's API system has an API for retrieving API documentation). These interfaces are for type hinting only. While it is true that I can just generate all combinations, that would make the file much much longer.

Is there a short and easy way to mark a set of keys of an interface as incompatible with each other?

0

There are 0 best solutions below