ADR Suggestion
Type hinting
#124
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
General
Since Python is a dynamic language, types are not declared before assignment, which makes it easy to accidentally pass objects of wrong types to arguments. Python is attempting to remedy this issue with type hints, which allow coders to hint at what type any object will be. Type hints does not change functionality of code, but is merely a tool which allows type-checkers to find errors and advanced IDE´s to more easily suggest code.
Current Implementation
Currently we are using type-hinting very loosely, writing type-hints in arguments and return types in most places, but often using the wrong types. Since type-hinting does not change functionality, this is not a critical issue, but it does mean that using a type-checker provides little-to-no help in finding errors in written code. We also use
TypeVars
andNewType
wrong in many places in our code.Proposed Implementation
I here propose that we add type-checking with
mypy
as a requirement before accepting new PR's. In other words, I propose that we properly type hint all our code so that we may benefit from error-finding with type-checkers.if TYPE_CHECKING
When importing classes and functions merely for type-hinting code, one should put those import statements withing an
if TYPE_CHECKING
block to avoid too many imports, and in particular, to avoid cyclic imports:type variables
TypeVar
TypeVars
are generic "wildcard" types which doesn't reflect any specific type. They are used when you want to type-hint that a certain argument type is also the one returned (or used elsewhere), no matter what type that might actually be, but just simply that they are the same:Here
Interface
is theTypeVar
and the above is the preferred method to denyTypeVars
. TheTypeVar
assumes the first type it is passed and then checks for that when used elsewhere in the same context.TypeVars
can also be constrained to only accept specific types:AnyStr
here is a type variable constrained to only accept the typesText
orbytes
, and only 1 of them within a given context (i.e.AnyStr
can't be used for bothText
andbytes
within a single method).TypeVars
can also be bound to an upper type:The type variable
Descriptors
here will acceptDescriptorNumber
and any of its subclasses, but again, only 1 specific type within a given context.A type variable can't be both bound and constrained.
Since
TypeVars
are local and context-dependent, they should be defined withinSince
TypeVars
are generic types, I believe they should be avoided in favour of explicit types whenever possible. But in cases where explicit types are impossible, theTypeVar
should have a self-explanatory name, to ease reading of the type. I.e. noTypeVars
with names like:_U
or similar, like what currently exists in our codebase.Type aliases
Python allows type aliases such as:
In this type alias,
Vector
is a synonym forlist[float]
. I propose to discourage/disallow type aliases, as it often makes types harder to read when reading code, unless the alias is well-known. Each new type alias should be proposed in anADR Suggestion
before being implemented due to potentially making the code harder to read.NewType
It is possible to create new types which are subclasses of existing types (or other
NewTypes
), with the use ofNewType
. For example, we could have a subtype of int:This new type "
Iterator
" is still anint
and anyint
function call will work on it, returning anint
type, butints
are notIterators
when type-checking, allowing for more complex type-checking. Like with type aliases, I propose discouraging/disallowing this for the same reason as with type-aliases, as it easily makes code more difficult to read, unless all the new types are well-known. Again, exceptions to this rule can be made but should require andADR Suggestion
.Beta Was this translation helpful? Give feedback.
All reactions