Add a short form for type casting variable assignments

One thing I ran into regularly is that I know what the type for a given variable for a server response is so I annotate it accordingly:

class Response(TypedDict):
    magic: boolean 

response: Response = httpx.get("/yay").json()

Generic clients do not know however the return type so their response is often something like dict[str, Any]. The type checker will fail for the above code, forcing me to use casting:

response = cast(Response, httpx.get("/yay").json())

This has a few downsides though:

  • requires importing the cast method
  • makes the code a bit harder to read, due to the method call and paranthesis, and makes the line longer
  • the Response type is now a runtime type, so no longer can live under a if TYPE_CHECKING import block (if defined in another file).
  • my lowest concern is the small runtime overhead of a no-op method call

I am suggesting to add a syntax that allow casting to remain behind the annotation, e.g.

response: Response! = httpx.get("/yay").json()

In this case the ! (or other construct that we agree on, e.g. ~Response would be an alternative) is a hint to the type checker that treat the line as if the right hand side of the assignment was type casted.

This is tangential to your proposal, but FYI, you can quote the type in cast to avoid needing to make it available at runtime:

if TYPE_CHECKING:
     from my_module import Response

response = cast("Response", httpx.get("/yay").json())

This also saves the runtime overhead of the doing the global lookup.

1 Like

Good tip Brian, doesn’t address the readability problem (it makes the line even longer) but works around the if TYPE_CHECKING import block issue.

At least in this particular example, just using

response: Response = httpx.get("/yay").json()

should work. json() is annotated as returning Any, so it can be assigned to a variable annotated with an arbitrary type. This is how I usually use these return types.

Sigh. The actual underlying client I am using is much more restrictive and is annotated correctly as must return a dictionary of some type. I was afraid, posting a specific, the conversation will get derailed on workarounds rather than on the actual topic, seems I was correct.

Also I would challenge your assertion that for a JSON type the correct return annotation is any. That is incorrect. With the introduction of recursive types it is possible to have a correct JSON type annotation, And some clients actually use that feature.

The value of a suggested addition to the language depends on whether there are other solutions to the problem. So talking about other solutions is not derailing and it is an important part of the discussion.

2 Likes