Utility types for Python, such as `Result`, `Option`, etc.
Project description
📦 typeric
typeric is a practical type utility toolkit for Python, focused on clarity, safety, and ergonomics. It was originally built to make my own development experience smoother, but I hope it proves useful to others as well.
It currently provides lightweight, pattern-matchable types like Result and Option — inspired by Rust — with plans to include more common type patterns and error-handling abstractions.
pip install typeric
🚀 Features
-
✅ Functional-style
Resulttype
Ok(value)andErr(error)with powerful.map(),.and_then(),.combine(),.spread()helpers — inspired by Rust’sResult. -
🌀 Lightweight
Optiontype
Some(value)andNONEto handle nullable data safely, with.map(),.unwrap_or(),.is_some()and more. -
🔁 Seamless conversion decorators
@resulty: Wraps any function to returnResultinstead of raising exceptions.@optiony: Wraps any function to returnOption, convertingNoneor exceptions intoNONE.
-
🧩 Pattern matching support
Supports Python’smatchsyntax via__match_args__for bothOk/ErrandSome/NONE. -
🔒 Immutable and composable
Safe and clean method chains using.map(),.combine(),.inspect(), etc. -
🔧 Clean type signatures
Fully typed:Result[T, E]andOption[T]with static analysis and IDE support. -
🛠️ Extensible foundation
Designed for easy extension — more algebraic types (Either,Validated, etc.) can be added naturally.
🔍 Quick Example
Result
from typeric.result import Result, Ok, Err, resulty, resulty_async, optiony, optiony_async
def parse_number(text: str) -> Result[int, str]:
try:
return Ok(int(text))
except ValueError:
return Err("Not a number")
match parse_number("42"):
case Ok(value):
print("Parsed:", value)
case Err(error):
print("Failed:", error)
# let function return Result[T,str]
@resulty
def add(x: int, y: int) -> int:
return x + y
res = add(1, 2)
if res.is_ok():
print("Result:", res.unwrap())
else:
print("Error:", res.err)
# let async function return Result[T,str]
@resulty_async
async def async_add(x: int, y: int) -> int:
return x + y
res = await async_add(1, 2)
if res.is_ok():
print("Result:", res.unwrap())
else:
print("Error:", res.err)
def func_a(x: int) -> Result[int, str]:
if x < 0:
return Err("negative input")
return Ok(x * 2)
@spreadable
def func_b(y: int) -> Result[int, str]:
a = func_a(y).spread()
return Ok(a + 1)
def test_func_b_success():
assert func_b(5) == Ok(11) # 5*2=10 +1=11
def test_func_b_propagate_error():
assert func_b(-2) == Err("negative input")
def validate_username(username: str) -> Result[str, str]:
if username.strip():
return Ok(username)
return Err("Username is empty")
def validate_age(age: int) -> Result[int, str]:
if age > 0:
return Ok(age)
return Err("Age must > 0")
def validate_email(email: str) -> Result[str, str]:
if "@" in email:
return Ok(email)
return Err("Invalid email")
# ✅ results combine
def validate_user_data(
username: str, age: int, email: str
) -> Result[tuple[tuple[str, int], str], str]:
return (
validate_username(username)
.combine(validate_age(age))
.combine(validate_email(email))
)
result1 = validate_user_data("alice", 30, "alice@example.com")
print(result1) # Ok((('alice', 30), 'alice@example.com'))
result2 = validate_user_data("", -5, "invalid-email")
print(result2.errs) # Err(['Username is empty', 'Age must > 0', 'Invalid email'])
Option
from typeric.option import Option, Some, NONE
from typeric.wrap_func import get_time_sync
def maybe_get(index: int, items: list[str]) -> Option[str]:
if 0 <= index < len(items):
return Some(items[index])
return NONE
match maybe_get(1, ["a", "b", "c"]):
case Some(value):
print("Got:", value)
case NONE:
print("Nothing found")
@get_time_sync # This decorator is used for synchronous functions to measure execution time.
@optiony
def get_number(x: int) -> int | None:
if x > 0:
return x
return None
@optiony_async
async def fetch_data(flag: bool) -> str | None:
if flag:
return "data"
return None
✅ Test
Run tests with:
uv run pytest -v
📦 Roadmap
- Async
Result OptionResultcombinatorsTry,Either,NonEmptyList, etc.
📄 License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file typeric-0.1.8.tar.gz.
File metadata
- Download URL: typeric-0.1.8.tar.gz
- Upload date:
- Size: 29.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c315c496db9dcb6149ad2e56c20e86f394992390c30504b48c13bb3ebdba0557
|
|
| MD5 |
cccee00fd7c0ad69f00df620cc885988
|
|
| BLAKE2b-256 |
69583a14178bfcbec5ee9612e5e77a21973dc00decd94835b9a24358cd9d0f22
|
File details
Details for the file typeric-0.1.8-py3-none-any.whl.
File metadata
- Download URL: typeric-0.1.8-py3-none-any.whl
- Upload date:
- Size: 8.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
971a9a42f734052b60f23098f8814d415e64a943636858821801d0b1755c0ec1
|
|
| MD5 |
af1ce5f0f04f9dfab633550da7c38784
|
|
| BLAKE2b-256 |
34554d0552b9c90e548a4062cd96a8d67885ecd7995354ead2c23614f5f69c77
|