I’m not sure whether this fits in Typing or in Ideas or in Help.

See numbers module · Issue #11863 · python/typeshed · GitHub.
Basically, the mathematical rule that a rational number divided by a rational number gives a rational number, is not described in the typing of that operation in the stdlib numbers module.
It may make sense to do what I propose in that thread, which is to have overload signatures like the following (pseudotypes like _ComplexLike being simplified to Complex):

That would certainly clear some type warnings I’m getting on my project.

However, would it be a constraint on the liberty officially permitted by the numbers module and related PEP ? In other words, should it be considered legal to make a subclass of Rational which when divided by a rational may give a complex ?

I would say no. These number types are supposed to represent the more abstract mathematical sets ^{[1]}, which have well defined operations between them. ℚ divide by ℚ is well defined to be within ℚ, and definitely not part of ℂ.

However, division by 0 throws a bit of wrench here. I would still say that keeping within ℚ is the best behavior, even if your extend your definition of ℚ to including a representation for infinity (like floating point numbers do).

These classes already imply extra restrictions on the behavior of these classes. For example, I would be annoyed if I get instances of these interfaces where I can’t assume communicative and associativity within a reasonable approximation (i.e. floats are fine)

Your proposed annotation for Rational.__truediv__ makes the class impossible to implement. These annotations would imply that an implementation of Complex needs to accept any other implementation of Complex in __truediv__, but how could a Complex type in one library know about a different Complex type in another and know how to handle it?

Those properties return more numbers classes (“_RealLike” in typeshed), which means there’s still no guarantee you can convert them to a class your library knows how to deal with.

Since conversion to the native types is provided, then all an implem has to provide is a conversion from the native types (it doesn’t even have to be part of the public API) in order to support every other implem.
If not, then they are not complying with the numbers API and while ignoring such edge cases is fine in my book, errors should not pass silently unless explicitly silenced ; in other words, a type # ignore is deserved for implementation that would not make the effort to support that.