Am 20.10.20 um 23:50 schrieb Eric Traut:
As Guido suggested, I've created a new draft PEP for "User-defined Type Guards". Input is welcome.
Draft Proposal (in fork): https://github.com/erictraut/peps/blob/master/pep-9999.rst Draft Proposal (branch compare): https://github.com/python/peps/compare/master...erictraut:master
Thank you for the PEP, I really like it. A few remarks:
* In the first example of the chapter "TypeGuard Type" you return "TypeGuard(len(val) == 2)" without explanation, while in the second example you just return "True" (my preference). * " User-defined type guards apply narrowing only in the positive case (the if clause)." Why? In the examples you give, type checkers should be able to safely narrow the "else" as well, shouldn't they?
There is one use case (that might be out of scope for this PEP) that is not covered, but is quite useful. I call it "type assertions". For example "assert isinstance(foo, Bar)" already narrows "foo" in the following code. I'll give one real-life example that we use quite a lot:
def parse_foo_json_request(j: Any) -> None: validate_foo_json(j) # Now the shape of j is known and data can be safely extracted.
def validate_foo_json(j: Any) -> None: # Do various checks on j, raise a complex exception if is doesn't # match the expected shape. pass
This can't be rewritten using a type guard, since the exception raised within the validation function depends on the exact problem with the given shape. This will later be used to give a detailed, structured explanation of went wrong to the caller of a web API. With the current PEP I would have to write this is something like this:
def parse_foo_json_request(j: Any) -> None: if not validate_foo_json(j): # dummy, will never happen raise RuntimeError(): # Now the shape of j is known and data can be safely extracted.
def validate_foo_json(j: Any) -> TypeGuard[Foo]: # Do various checks on j, raise a complex exception if is doesn't # match the expected shape. return True
One idea I have (not though through) is to be able to write something like this:
def validate_foo_json(j: TypeGuard[Foo]) -> None: # Do various checks on j, raise a complex exception if is doesn't # match the expected shape. return True
I.e. if the type guard is at an argument position, the validation function will not return if it doesn't match the type.
But as I said, this might be out of scope of the current PEP.