Skip to main content

Tiny runtime checker for typing annotations (dict[str,str], list[T], unions, literals) with an Option-like API.

Project description

typecheck-runtime

Tiny runtime checker for typing annotations with an Option-like API.

py-typecheck solves a very specific problem:

I have a value (object or Any) and I want to check if the value refers to specific typing annotation.

Does not parse data. Does not transforms data. Just checks structure and returns refered value or None if validation failed.

Installation

pip install typecheck-runtime

Python  3.10

Core idea

Main function is checked

from py_typecheck import checked

Acts like Option[T] or Rust-like Some(T, None):

  • returns value if matches the type
  • returns None if validation failed

No exceptions, no side-efects.


Basic usage

value: object = {"a": 1}

if (d := checked(value, dict[str, int])) is not None:
    print(d["a"] + 1)

Important

  • always compare against None when using checked
  • do not rely on truthiness (0, False, [] are valid values!)
  • bool is treated as not matching int (so True wont pass as int)

checked_or

If you want the same runtime check as checked(), but with a convenient fallback, use checked_or().

  • returns the original value if it matches the target type
  • otherwise returns the provided default

This is especially handy when you want a safe, typed value in one expression without handling None.

from py_typecheck import checked_or

age: object = "not-a-number"

# returns 10 because "not-a-number" is not an int
value = checked_or(age, int, 10)

Works with typing constructs the same way as checked():

from py_typecheck import checked_or

payload: object = {"tags": ["a", "b"]}

tags = checked_or(payload, dict[str, list[str]], {"tags": []})["tags"]

Important notes:

  • checked_or() relies on checked() semantics (including the bool vs int rule)
  • default should already be the correct value you want to use (no coercion happens)

Supported typing constructs

py-typecheck supports common runtime-validable constructs from typing:

Primitive types

checked(1, int)          # 1
checked("x", int)        # None
checked(True, int)       # None

Note: bool is not considered an int in this library.

Union (X | Y, typing.Union)

checked(1, int | str)      # 1
checked("x", int | str)    # "x"
checked(1.5, int | str)    # None

List / Set / FrozenSet

checked([1, 2], list[int])           # [1, 2]
checked({1, 2}, set[int])            # {1, 2}
checked(frozenset({1}), frozenset[int])

Nested structures work as expected:

checked([[1, 2], [3]], list[list[int]])

Dict

checked({"a": 1}, dict[str, int])
checked({"a": "x"}, dict[str, int])   # None

Supports unions and nesting:

checked({"a": [1, 2]}, dict[str, list[int]])

Tuple

Fixed-length:

checked((1, "x"), tuple[int, str])

Variadic:

checked((1, 2, 3), tuple[int, ...])

Literal

from typing import Literal

checked(True, Literal[True])    # True
checked(False, Literal[True])   # None

Any

from typing import Any

checked(object(), Any)   # always matches

is_type

There is also a boolean helper:

from py_typecheck import is_type

if is_type(value, dict[str, int]):
    ...
  • It returns only True / False.
  • For most code paths, checked is preferred, because it avoids type confusion and double-checking mistakes.

Design principles

  • Explicit is better than clever
  • No exceptions for control flow
  • No implicit casting
  • No data mutation
  • No dependency on dataclasses or models
  • One function, one responsibility

This is not a validator framework. This is a runtime structural check with a safe return value.

Non-goals

py-typecheck intentionally does not:

  • coerce types ("1" → 1)
  • fill defaults
  • validate constraints (ranges, regexes, etc.)
  • replace pydantic or attrs

If you want parsing + validation + coercion → use Pydantic. If you want “is this already the right shape?” → use this.


Comparison

Tool Purpose
isinstance Runtime type only
typing Static type checking
pydantic Parsing + validation + coercion
py-typecheck Runtime structural check only

Development status

  • Fully typed (basedpyright strict)
  • Tested against Python 3.10 – 3.13
  • CI + lint + coverage
  • Small surface area, easy to audit

License MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

typecheck_runtime-0.2.0.tar.gz (7.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

typecheck_runtime-0.2.0-py3-none-any.whl (5.4 kB view details)

Uploaded Python 3

File details

Details for the file typecheck_runtime-0.2.0.tar.gz.

File metadata

  • Download URL: typecheck_runtime-0.2.0.tar.gz
  • Upload date:
  • Size: 7.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for typecheck_runtime-0.2.0.tar.gz
Algorithm Hash digest
SHA256 9e61569045a0d9f346c677e7da49004ebc4b861b25c49c2479391808d28e071a
MD5 d93cb90fca58e1976e69116126446da1
BLAKE2b-256 ac70869d7c6a217b1ba88d6b4a894221964d5b7c63b1110ba9bf101133ac0071

See more details on using hashes here.

Provenance

The following attestation bundles were made for typecheck_runtime-0.2.0.tar.gz:

Publisher: release.yml on schizza/py-typecheck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file typecheck_runtime-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for typecheck_runtime-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 757a93909928c333c112761fef994e87d899ba3a744e05f26a1d698d83e7b304
MD5 a700e6cfb6775def5687febd0d2943b4
BLAKE2b-256 6f19ffa7e20b9aab5a5896bdeb54cc062c57f44fd8cb640945d1a3e9f8bfc7cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for typecheck_runtime-0.2.0-py3-none-any.whl:

Publisher: release.yml on schizza/py-typecheck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page