TypeForm: Spelling for a type annotation object at runtime

Okay, sorry I didn’t have all the time to get into all of what I saw as issues with this in-depth earlier…

  1. By having Annotated implicitly strip annotations immediately and be special cased rather than having a way to handle Annotated, you force runtime libraries to handle annotated immediately and not have any helper functions it might get passed to.

  2. By having Annotated have this behavior, it’s not possible to type typing.get_args in a way that allows runtime libraries to work with annotated without a type ignore.

These two can be demonstrated pretty readily with (The alternative parameterization of TypeForm I mentioned)

def handle_user_input(
    typ: type[T] | TypeForm[Annotated, T, *Anns], user_input: str
) -> T:
    if typing.get_origin(typ) is Annotated:
        # if the type system implicitly converts to T instead, 
        # this is considered unreachable code instead
        # as Annotated isn't compatible with type
        # and this also isn't a valid assignment to typ
        typ, *annotations = typing.get_args(typ)  
    else:
        annotations = ()

    # call some helper function
    value = convert(user_input, typ)  # raises if can't convert to this type

    for annotation in annotations:
        if isinstance(annotation, Validator):
            annotation.validate(value)  # raises conditionally

    return value

This is a pretty clear case of handling a specific type form, and it’s something that was quite recently something runtime validation libraries were told they needed to wait for type form for. I don’t think people envisioned a situation where type form wouldn’t allow expressing what those libraries were doing within the type system.

If this pep does things like an implicit conversion from Annotated to the inner type rather than provide the tools to get at the inner type in a type safe manner, or the inability to type which type forms they can handle, those libraries will have lost cababilties of what they can type between that change and this pep.

The concern about type variable bounds doesn’t even need to come into play for there to be an issue with the proposed version and not allowing constraining to a specific type form.