I have an abstract base class ParserNode, with a bunch of concrete subclasses (StartTag, RawText, etc). I have a function that takes a ParserNode and does different things based on which subtype it is. I'd like to ensure that mypy will complain if I ever add a new ParserNode subclass without amending this function to handle the new type as well. Naively, I'd write this as: import typing def doTheThing(node: ParserNode) -> None: if isinstance(node, StartTag): ... elif isinstance(node, RawText): ... else: typing.assert_never(node) However, this doesn't work - mypy immediately complains that I'm not handling the ParserNode type. But that's an abstract base class, declared with meta=ABCMeta and with an @abstractmethod, so it's impossible for a variable to have that as its concrete type. So far, the only workaround I've found for this is to manually declare a union of subtypes and use that, like: import typing ParserNodeSubs: typing.TypeAlias = "StartTag | RawText" def doTheThing(node: ParserNode) -> None: node = typing.cast(ParserNodeSubs, node) if isinstance(node, StartTag): ... elif isinstance(node, RawText): ... else: typing.assert_never(node) This works as I want it to, but it's a little annoyingly verbose for a situation that I believe shouldn't require it, requiring me to manually maintain the list of ParserNodeSubs (tho only in one spot) and then manually cast variables when I need them. Is there a better way to declare these classes that makes it work automatically? Continue reading...