Python equivalent to `as` type assertion in TypeScript
Question:
In TypeScript you can override type inferences with the as
keyword
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
Are there similar techniques in Python3.x typing without involving runtime casting? I want to do something like the following:
class SpecificDict(TypedDict):
foo: str
bar: str
res = request(url).json() as SpecificDict
Answers:
If I understand you correctly, you’re looking for typing.cast
:
from typing import cast
res = cast(dict, request(url))
This will assert to a typechecker that res
is assigned to a value that is a dictionary, but it won’t have any effects at runtime.
as
allows for explicit casting of a value to a sub- or supertype of the real value. This is relevant for a statically typed language, not so much for a dynamically typed language like Python. The typing
module lets you provide static type hints that a third-party tool like mypy
can use to look for static-type errors before you run your code, so let’s focus on it.
typing.cast
provides a general escape hatch for static typing: you are not restricted to sub- or super types of the actual type. You can claim that a value x
has any type you like, and mypy
will believe you. For example,
x: str = typing.cast(int, 5) # Sure, OK, 5 is a string
assert isinstance(x, str) # Oops, I guess not.
An as
-like use of cast
might be
x: Optional[int] = 3
y: int = x # fail, x might be None at runtime
z: int = typing.cast(int, x) # don't worry, I promise x isn't None
Upcasting is a little easier, as a type annotation will suffice.
x: bool = True
y: int = x # Ok, bool is a subtype of int
mypy
does perform type narrowing in certain contexts. For example, if a certain block of code can only be reached if a certain run-time type check passes, mypy
will infer the type implied by the successful check.
x : Optional[int] = 5
x += 1 # static type error, since None doesn't support +=
but
x : Optional[int] = 5
if x is not None:
x += 1 # OK; if x is not None is true, then we can assume x: int
In TypeScript you can override type inferences with the as
keyword
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
Are there similar techniques in Python3.x typing without involving runtime casting? I want to do something like the following:
class SpecificDict(TypedDict):
foo: str
bar: str
res = request(url).json() as SpecificDict
If I understand you correctly, you’re looking for typing.cast
:
from typing import cast
res = cast(dict, request(url))
This will assert to a typechecker that res
is assigned to a value that is a dictionary, but it won’t have any effects at runtime.
as
allows for explicit casting of a value to a sub- or supertype of the real value. This is relevant for a statically typed language, not so much for a dynamically typed language like Python. The typing
module lets you provide static type hints that a third-party tool like mypy
can use to look for static-type errors before you run your code, so let’s focus on it.
typing.cast
provides a general escape hatch for static typing: you are not restricted to sub- or super types of the actual type. You can claim that a value x
has any type you like, and mypy
will believe you. For example,
x: str = typing.cast(int, 5) # Sure, OK, 5 is a string
assert isinstance(x, str) # Oops, I guess not.
An as
-like use of cast
might be
x: Optional[int] = 3
y: int = x # fail, x might be None at runtime
z: int = typing.cast(int, x) # don't worry, I promise x isn't None
Upcasting is a little easier, as a type annotation will suffice.
x: bool = True
y: int = x # Ok, bool is a subtype of int
mypy
does perform type narrowing in certain contexts. For example, if a certain block of code can only be reached if a certain run-time type check passes, mypy
will infer the type implied by the successful check.
x : Optional[int] = 5
x += 1 # static type error, since None doesn't support +=
but
x : Optional[int] = 5
if x is not None:
x += 1 # OK; if x is not None is true, then we can assume x: int