{"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":"en","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,"last_verified":"2026-04-10T00:00:00.000Z","next_check":"2026-07-09T00:00:00.000Z"}