TS has been used as a motivation and justification for the term, and as such I think that we should not deviate that much from how type guards work on Typescript. Unfortunately there is no specification of user-defined typeguards, as TS stopped maintaining the language spec some years ago. However, they do specify what a type guard is (see section 4.2 of
https://javascript.xgqfrms.xyz/pdfs/TypeScript%20Language%20Specification.pdf), so I guess the implemented behavior for user-defined type guards is compatible with that definition.
Maybe there should be a prelude PEP norming how a type guard should be treated by a type checker.
There are also some important differences between the two:
- In TS, user defined typeguards are compatible with (...) => bool. However the proposed PEP says:
"TypeGuard is a distinct type from bool. It is not a subtype of bool. Therefore, Callable[..., TypeGuard[int]] is not assignable to Callable[..., bool].", this
prevents using typeguards as predicates for filtering functions.
- TS does apply narrowing in the negative branch. However, the proposal explicitly mandates not to narrow in such case. "User-defined type guards apply narrowing only in the positive case (the if clause). The type is not narrowed in the negative case."
This is important to clarify, as then the semantics of the type guard would be different. Basically in TS a typeguard MUST return true whenever the condition holds, however in the python proposal returning true means you can prove the condition holds. I think we should require the former and let the type checker decide whether they want to narrow in the negative case. I imagine the narrowing logic for negative cases is already implemented as they currently do it for isinstance checks.
- Not clear if type guards should be applied in and/or expressions: "When a conditional statement includes a call to a user-defined type guard function"
- TS requires "compatible" narrowing. This was ruled out because that "require[s] that we articulate all of the subtle ways in which the rules differ and under what specific circumstances the constrains are relaxed" and "it is safe to assume that they are interested in type safety and will not write their type guard functions in a way that will undermine type safety or produce nonsensical results". However, the latter statement may be true initially, but after refactoring a type one could potentially end up with a non-sensical guard.