{"id":2654,"library":"optype","title":"OpType","description":"OpType is a Python library (v0.17.0) providing building blocks for precise and flexible type hints, offering single-method protocols for dunder methods, exact types that reject sneaky subtypes, and typed operators. It aims to make type-checking more robust and expressive. The library is actively maintained with somewhat frequent minor releases and supports various modern type checkers like mypy, pyright, and pyrefly.","status":"active","version":"0.17.0","language":"python","source_language":"en","source_url":"https://github.com/jorenham/optype/","tags":["type hinting","protocols","static analysis","mypy","pyright","numpy","type checking","runtime checkable"],"install":[{"cmd":"pip install optype","lang":"bash","label":"Core library"},{"cmd":"pip install optype[numpy]","lang":"bash","label":"With NumPy support"}],"dependencies":[{"reason":"Required for the 'numpy' extra to ensure static typing compatibility with NumPy versions.","package":"numpy-typing-compat","optional":true}],"imports":[{"symbol":"CanAdd","correct":"from optype import CanAdd"},{"symbol":"CanAbs","correct":"from optype import CanAbs"},{"symbol":"JustAny","correct":"from optype import JustAny"},{"symbol":"HasDataclassFields","correct":"from optype.dataclasses import HasDataclassFields"},{"note":"optype.do_add provides a correctly typed, runtime-checkable version of the add operator.","wrong":"import operator; operator.add","symbol":"do_add","correct":"from optype import do_add"}],"quickstart":{"code":"from typing import Literal, TypeVar\nfrom optype import CanMul, CanRMul\n\nY = TypeVar('Y')\nTwo: Literal[2] = 2\n\ndef twice(x: CanRMul[Literal[2], Y]) -> Y:\n    return Two * x\n\n# Example usage with different types\nprint(f\"twice(2) = {twice(2)}\")\nprint(f\"twice(3.14) = {twice(3.14)}\")\nprint(f\"twice('I') = {twice('I')}\")\n\n# Fallback for types that implement __mul__ but not __rmul__\ndef twice_flexible(x: CanRMul[Literal[2], Y] | CanMul[Literal[2], Y]) -> Y:\n    if isinstance(x, CanRMul):\n        return Two * x\n    else:\n        return x * Two\n\nprint(f\"twice_flexible(5) = {twice_flexible(5)}\")","lang":"python","description":"This example demonstrates how to define a function `twice` that accepts any type `x` for which `2 * x` is valid, using `optype.CanRMul` for precise type hinting. It also shows a more flexible version using `CanMul` as a fallback, leveraging `isinstance` due to `optype` protocols being runtime-checkable."},"warnings":[{"fix":"Review the specific `Can*` protocols affected and adjust type parameter usage according to the updated documentation or remove redundant parameters.","message":"In v0.15.0, several `optype.Can*` generic type parameters (e.g., `CanBytes`, `CanStr`, `CanLen`) intended for literal types were removed. This impacts protocols like `CanBytes`, `CanStr`, `CanIndex`, `CanRepr`, etc.","severity":"breaking","affected_versions":">=0.15.0"},{"fix":"Remove the generic type parameter from `HasDataclassFields` usage. For example, change `HasDataclassFields[T]` to `HasDataclassFields`.","message":"The `optype.dataclasses.HasDataclassFields` protocol had its generic type parameter removed in v0.17.0, and `__dataclass_fields__` was turned into a `ClassVar`. This fixes an assignability issue with dataclass instances but requires adjusting code that relied on the generic parameter.","severity":"breaking","affected_versions":">=0.17.0"},{"fix":"Install with `pip install optype[numpy]` or explicitly `pip install numpy-typing-compat` alongside `optype`.","message":"When using `optype.numpy`, ensure `numpy-typing-compat` is installed. As of v0.13.0, this dependency is required for robust static typing compatibility with NumPy versions and is automatically installed with the `optype[numpy]` extra.","severity":"gotcha","affected_versions":">=0.13.0"},{"fix":"Use `optype` protocols for type checking and runtime `isinstance` checks, but inherit from standard ABCs or implement methods directly in your classes rather than inheriting from `optype.Can*` protocols.","message":"While `optype` protocols are runtime-checkable (e.g., `isinstance('snail', optype.CanAdd)`), it is considered bad practice to use them as base classes for your own implementations. They are pure interfaces, not abstract base classes like `collections.abc` protocols.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"search_vec":"'activ':48 'aim':35 'analysi':70 'block':10 'build':9 'check':40,75 'checkabl':77 'checker':60 'dunder':23 'exact':25 'express':44 'flexibl':14 'frequent':52 'hint':16,67 'librari':6,46 'like':61 'maintain':49 'make':37 'method':20,24 'minor':53 'modern':58 'mypi':62,71 'numpi':73 'offer':17 'oper':33 'optyp':1,2 'precis':12 'protocol':21,68 'provid':8 'pyrefli':65 'pyright':63,72 'python':5 'reject':28 'releas':54 'robust':42 'runtim':76 'singl':19 'single-method':18 'sneaki':29 'somewhat':51 'static':69 'subtyp':30 'support':56 'type':15,26,32,39,59,66,74 'type-check':38 'v0.17.0':7 'various':57","created_at":"2026-04-11T01:37:11.870154+00:00","updated_at":"2026-04-16T17:47:59.771976+00:00","problems":[{"fix":"Install the library using pip: `pip install optype`","cause":"The 'optype' library is not installed in the Python environment, or the Python interpreter cannot find it in its search path.","error":"ModuleNotFoundError: No module named 'optype'"},{"fix":"Install the missing dependency: `pip install typing_extensions`","cause":"When using 'optype' on Python versions 3.13 or newer, a dependency on 'typing_extensions' might incorrectly be triggered, leading to this error if 'typing_extensions' is not installed. This was a known issue fixed in optype v0.17.0, but could still occur in specific environments or if using a slightly older patch version.","error":"ModuleNotFoundError: No module named 'typing_extensions'"},{"fix":"Ensure that the value passed to the `optype.Exact` annotation is of the exact specified type, not a subtype. If a subtype is acceptable, use `BaseClass` directly or `typing.Union` instead of `optype.Exact`.","cause":"This Mypy (or similar type checker) error occurs when a function or variable annotated with `optype.Exact[BaseClass]` is provided with an instance of `DerivedClass`, where `DerivedClass` is a subtype of `BaseClass`. `optype.Exact` specifically rejects subtypes, requiring the type to be precisely `BaseClass`.","error":"Argument 1 to \"my_function\" has incompatible type \"DerivedClass\"; expected \"optype.Exact[BaseClass]\""},{"fix":"Modify `MyObject` to implement the `__add__` dunder method with a signature compatible with `optype.CanAdd[int, int]`, or pass an object that already satisfies the `optype.CanAdd` protocol.","cause":"This Mypy (or similar type checker) error indicates that an object of type `MyObject` was passed to a function expecting a type that implements the `optype.CanAdd` protocol (meaning it must have a `__add__` method compatible with the specified arguments and return type), but `MyObject` does not correctly implement this protocol.","error":"Argument 1 to \"my_function\" has incompatible type \"MyObject\"; expected \"optype.CanAdd[int, int]\""}],"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"0.18.0","cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/jorenham/optype","docs":"https://jorenham.github.io/optype/","changelog":"https://github.com/jorenham/optype/releases","pypi":"https://pypi.org/project/optype/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["type-stubs","testing"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-28","last_verified":"2026-08-28","next_check":"2026-07-28","install_tag":null}}