There are a couple of fundamental differences between TypeScript and Python with mypy. It is closer to how ECMAScript with Google Closure Compiler works than how TypeScript works. Or, how modern IDEs use type hints in documentation comments.
First off, TypeScript has a type system and typing rules. Python does not have a type system or typing rules. Python only has syntax for type hints. However, Python itself does not do anything with those type hints. This is left to third-party tools. This has some advantages and some disadvantages. The biggest advantage is that you can choose the tool that is most useful for your particular application domain. The biggest disadvantage is that when you write down a type hint, you don't actually know what it means … because it has no meaning. The meaning is assigned by an external third-party tool.
In other words: Python type hints have no defined semantics.
The second difference is that TypeScript has a separate type language. Python's type language instead is just Python. That means that a type hint must be a syntactically valid Python expression. In fact, type hints are evaluated at runtime, so not only do they have to be syntactically valid Python, they need to be semantically valid Python as well; they need to be executable without errors or exceptions, even if you never actually use them at runtime and only use them for static type checking e.g. with mypy. (That is the main reason for the typing module: to provide functions and objects that allow you to turn syntax that you would like to write (e.g. generics) into valid runtime expressions.)
In other words: Python type hints have no separate syntax, they are just Python expressions.
So, the first thing this tells us is that whatever potential solution you come up with, it must be syntactically and semantically valid Python. arg! is not syntactically valid Python. So, an exact equivalent to the TypeScript syntax is not possible.
So, we have to check whether we can find a semantic equivalent with a different syntax. The possible places where we could find one are:
Looking at those three, we find that we don't find anything. This isn't proof that something like this doesn't exist (absence of evidence is not evidence of absence), but it is a good indication.
Mypy only supports the equivalent of a TypeScript Type Guard:
if arg is None:
pass
else:
# mypy knows that `arg` is a `str` here
if arg is not None:
# mypy knows that `arg` is a `str` here
if not arg:
pass
else:
# mypy knows that `arg` is a `str` here
if arg:
# mypy knows that `arg` is a `str` here
In case you cannot provide such a type guard, or you absolutely 100% know arg cannot be None at this point, under no circumstance, EVER, you can provide a type assertion:
assert arg is not None
# mypy knows that `arg` is a `str` here
A type assertion will also let mypy know that arg cannot be None after that point. This is explicitly documented in the mypy documentation.
This might be the closest thing semantically to the TypeScript ! type operator. In fact, the ! operator is really nothing but an assertion: "Hey, type checker, trust me, I know something you don't." Which is exactly the same thing the Python assertion also says.