'Python Typing: Subtype Literal

In Python, I would like to "narrow-down", or "sub-type" a Literal: I would like to have two Literal type aliases, Parent and Child, and I would like to assure typing-wise, that Child is a subtype of Parent, i.e. that the arguments of Child form a subset of the arguments of Parent:

Parent = Literal['a', 'b']
Daughter = Literal['a']   # Should be OK
Son = Literal['b']        # Should be OK
NotAChild = Literal['c']  # Should not be OK, because 'c' is not in Parent.__args__

Is it possible to express this relation between the children and the parent type, so that the typecheckers will throw an error on NotAChild? (If yes, how?)

Subclassing a Literal type is not allowed. The following code throws a TypeError: Cannot subclass typing.Literal['a', 'b']

class Child(Parent):
    pass


Solution 1:[1]

It is probably impossible with static type checkers. You can enforce it on runtime, if applicable, with typing.get_args:

from typing import Literal, get_args

Parent = Literal['a', 'b']
Daughter = Literal['a']
Son = Literal['b']
NotAChild = Literal['c']

assert set(get_args(Daughter)) <= set(get_args(Parent))  # OK
assert set(get_args(Son)) <= set(get_args(Parent))  # OK
assert set(get_args(NotAChild)) <= set(get_args(Parent))  # AssertionError

It is far from excellent (even if you refactor to extract function like assert_literal_child), because this approach mixes type checking and runtime. However, you can put this into separate test file and say that both this test and mypy are complementary parts of your test suite.

Solution 2:[2]

I would like to quote Jelle Zijlstra's answer from the typing-sig mailing list:

You can do this as with any other subtyping relationship, by creating a dummy function and passing your object to it.

With the definitions of the question, this results in:

def demands_parent(p: Parent) -> None:
    pass

def check(x: NotAChild) -> None:
    demands_parent(x)  # type checker error

This is probably not ideal, as it requires writing the dummy functions - it would be preferable if the relation between the Parent and the Child classes would be defined directly when defining the types. But this solutions does not require any runtime-checks, and relies only on the typecheckers.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 SUTerliakov
Solution 2 Jonathan Scholbach