def typehint_issubclass(
    possible_subclass: Any,
    possible_superclass: Any,
    *,
    treat_mutable_superclasss_as_immutable: bool = False,
    treat_literals_as_union_of_types: bool = True,
    treat_any_as_subtype_of_everything: bool = False,
) -> bool:
    """Check if a type hint is a subclass of another type hint.

    Args:
        possible_subclass: The type hint to check.
        possible_superclass: The type hint to check against.
        treat_mutable_superclasss_as_immutable: Whether to treat target classes as immutable.
        treat_literals_as_union_of_types: Whether to treat literals as a union of their types.
        treat_any_as_subtype_of_everything: Whether to treat Any as a subtype of everything. This is the default behavior in Python.

    Returns:
        Whether the type hint is a subclass of the other type hint.
    """
    if possible_subclass is possible_superclass or possible_superclass is Any:
        return True
    if possible_subclass is Any:
        return treat_any_as_subtype_of_everything
    if possible_subclass is NoReturn:
        return True

    provided_type_origin = get_origin(possible_subclass)
    accepted_type_origin = get_origin(possible_superclass)

    if provided_type_origin is None and accepted_type_origin is None:
        # In this case, we are dealing with a non-generic type, so we can use issubclass
        return issubclass(possible_subclass, possible_superclass)

    if treat_literals_as_union_of_types and is_literal(possible_superclass):
        args = get_args(possible_superclass)
        return any(
            typehint_issubclass(
                possible_subclass,
                type(arg),
                treat_mutable_superclasss_as_immutable=treat_mutable_superclasss_as_immutable,
                treat_literals_as_union_of_types=treat_literals_as_union_of_types,
                treat_any_as_subtype_of_everything=treat_any_as_subtype_of_everything,
            )
            for arg in args
        )

    if is_literal(possible_subclass):
        args = get_args(possible_subclass)
        return all(
            _isinstance(
                arg,
                possible_superclass,
                treat_mutable_obj_as_immutable=treat_mutable_superclasss_as_immutable,
                nested=2,
            )
            for arg in args
        )

    provided_type_origin = (
        Union if provided_type_origin is types.UnionType else provided_type_origin
    )
    accepted_type_origin = (
        Union if accepted_type_origin is types.UnionType else accepted_type_origin
    )

    # Get type arguments (e.g., [float, int] for dict[float, int])
    provided_args = get_args(possible_subclass)
    accepted_args = get_args(possible_superclass)

    if accepted_type_origin is Union:
        if provided_type_origin is not Union:
            return any(
                typehint_issubclass(
                    possible_subclass,
                    accepted_arg,
                    treat_mutable_superclasss_as_immutable=treat_mutable_superclasss_as_immutable,
                    treat_literals_as_union_of_types=treat_literals_as_union_of_types,
                    treat_any_as_subtype_of_everything=treat_any_as_subtype_of_everything,
                )
                for accepted_arg in accepted_args
            )
        return all(
            any(
                typehint_issubclass(
                    provided_arg,
                    accepted_arg,
                    treat_mutable_superclasss_as_immutable=treat_mutable_superclasss_as_immutable,
                    treat_literals_as_union_of_types=treat_literals_as_union_of_types,
                    treat_any_as_subtype_of_everything=treat_any_as_subtype_of_everything,
                )
                for accepted_arg in accepted_args
            )
            for provided_arg in provided_args
        )
    if provided_type_origin is Union:
        return all(
            typehint_issubclass(
                provided_arg,
                possible_superclass,
                treat_mutable_superclasss_as_immutable=treat_mutable_superclasss_as_immutable,
                treat_literals_as_union_of_types=treat_literals_as_union_of_types,
                treat_any_as_subtype_of_everything=treat_any_as_subtype_of_everything,
            )
            for provided_arg in provided_args
        )

    provided_type_origin = provided_type_origin or possible_subclass
    accepted_type_origin = accepted_type_origin or possible_superclass

    if treat_mutable_superclasss_as_immutable:
        if accepted_type_origin is dict:
            accepted_type_origin = Mapping
        elif accepted_type_origin is list or accepted_type_origin is set:
            accepted_type_origin = Sequence

    # Check if the origin of both types is the same (e.g., list for list[int])
    if not safe_issubclass(
        provided_type_origin or possible_subclass,
        accepted_type_origin or possible_superclass,
    ):
        return False

    # Ensure all specific types are compatible with accepted types
    # Note this is not necessarily correct, as it doesn't check against contravariance and covariance
    # It also ignores when the length of the arguments is different
    return all(
        typehint_issubclass(
            provided_arg,
            accepted_arg,
            treat_mutable_superclasss_as_immutable=treat_mutable_superclasss_as_immutable,
            treat_literals_as_union_of_types=treat_literals_as_union_of_types,
            treat_any_as_subtype_of_everything=treat_any_as_subtype_of_everything,
        )
        for provided_arg, accepted_arg in zip(
            provided_args, accepted_args, strict=False
        )
        if accepted_arg is not Any
    )
Check if a type hint is a subclass of another type hint.

    Args:
        possible_subclass: The type hint to check.
        possible_superclass: The type hint to check against.
        treat_mutable_superclasss_as_immutable: Whether to treat target classes as immutable.
        treat_literals_as_union_of_types: Whether to treat literals as a union of their types.
        treat_any_as_subtype_of_everything: Whether to treat Any as a subtype of everything. This is the default behavior in Python.

    Returns:
        Whether the type hint is a subclass of the other type hint.
    
reflex/utils/types.py