Skip to main content

phantom-types

CI Build Status Documentation Build Status Test coverage report
PyPI Package Python versions

Phantom types for Python will help you make illegal states unrepresentable and avoid shotgun parsing by enabling you to practice "Parse, don't validate".

Checkout the complete documentation on Read the Docs →

Installation

$  python3 -m pip install phantom-types

Extras

There are a few extras available that can be used to either enable a feature or install a compatible version of a third-party library.

Extra name Feature
[dateutil] Installs python-dateutil. Required for parsing strings with TZAware and TZNaive.
[phonenumbers] Installs phonenumbers. Required to use phantom.ext.phonenumbers.
[pydantic] Installs pydantic.
[hypothesis] Installs hypothesis.
[all] Installs all of the above.
$  python3 -m pip install phantom-types[all]

Examples

By introducing a phantom type we can define a pre-condition for a function argument.

from phantom import Phantom
from phantom.predicates.collection import contained


class Name(str, Phantom, predicate=contained({"Jane", "Joe"})): ...


def greet(name: Name):
    print(f"Hello {name}!")

Now this will be a valid call.

greet(Name.parse("Jane"))

... and so will this.

joe = "Joe"
assert isinstance(joe, Name)
greet(joe)

But this will yield a static type checking error.

greet("bird")

To be clear, the reason the first example passes is not because the type checker somehow magically knows about our predicate, but because we provided the type checker with proof through the assert. All the type checker cares about is that runtime cannot continue executing past the assertion, unless the variable is a Name. If we move the calls around like in the example below, the type checker would give an error for the greet() call.

joe = "Joe"
greet(joe)
assert isinstance(joe, Name)

Runtime type checking

By combining phantom types with a runtime type-checker like beartype or typeguard, we can achieve the same level of security as you'd gain from using contracts.

import datetime
from beartype import beartype
from phantom.datetime import TZAware


@beartype
def soon(dt: TZAware) -> TZAware:
    return dt + datetime.timedelta(seconds=10)

The soon function will now validate that both its argument and return value is timezone aware, e.g. pre- and post conditions.

Pydantic support

Phantom types are ready to use with pydantic and have integrated support out-of-the-box. Subclasses of Phantom work with both pydantic's validation and its schema generation.

class Name(str, Phantom, predicate=contained({"Jane", "Joe"})):
    @classmethod
    def __schema__(cls) -> Schema:
        return super().__schema__() | {
            "description": "Either Jane or Joe",
            "format": "custom-name",
        }


class Person(BaseModel):
    name: Name
    created: TZAware


print(json.dumps(Person.model_json_schema(), indent=2))

The code above outputs the following JSONSchema.

{
  "properties": {
    "name": {
      "description": "Either Jane or Joe",
      "format": "custom-name",
      "title": "Name",
      "type": "string"
    },
    "created": {
      "description": "A date-time with timezone data.",
      "format": "date-time",
      "title": "TZAware",
      "type": "string"
    }
  },
  "required": ["name", "created"],
  "title": "Person",
  "type": "object"
}

Development

Install development requirements, preferably in a virtualenv:

$ python3 -m pip install .[all,test,type-check]

Run tests:

$ pytest
# or
$ make test

Run type checker:

$ mypy

Linters and formatters are set up with goose, after installing it you can run it as:

# run all checks
$ goose run --select=all
# or just a single hook
$ goose run mypy --select=all

In addition to static type checking, the project is set up with pytest-mypy-plugins to test that exposed mypy types work as expected, these checks will run together with the rest of the test suite, but you can single them out with the following command.

$ make test-typing

Metadata

Release files for phantom-types 4.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for phantom-types 4.0.0
File Size Uploaded Provenance Actions
phantom_types-4.0.0.tar.gz 28.0 kB With provenance Details for phantom_types-4.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for phantom-types 4.0.0
File Interpreter ABI Platform Actions
phantom_types-4.0.0-py3-none-any.whl Python 3 none any Details for phantom_types-4.0.0-py3-none-any.whl

Total release size: 60.1 kB

Release files / phantom_types-4.0.0.tar.gz

Download URL phantom_types-4.0.0.tar.gz
Size 28.0 kB
Tags Source
SHA-256 checksum
How to use checksums
f33fffd98cdb9bf7cde553b334684028583fad57cd91f6b8910518887b3104a2
BLAKE2b-256 checksum
How to use checksums
1350d622a1193e98131c3e73682fc8d5da5af1760938912b833a9cad5a19ed23
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

Release files / phantom_types-4.0.0-py3-none-any.whl

Download URL phantom_types-4.0.0-py3-none-any.whl
Size 32.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c41cdf30765547f8a27e5f3a2a93ff050b3ba5a27f18d792efd40cd8b5f43aa6
BLAKE2b-256 checksum
How to use checksums
e6ee92ac23556f1ed218cea2a5d8dee785ab5fa1f5e94ebe63957143303ffe7b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

Security for phantom-types 4.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for phantom_types-4.0.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

4.0.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page