Skip to main content

typenames : String representations of type annotations

Docs Status PyPI conda-forge Supported Python versions tests codecov

typenames is a configurable Python library for creating string representations of type annotations. By default, it produces compact representations by removing standard library module names. Configurable options include standardizing on | operator syntax for unions or standard collections classes for generics.

import typing
from typenames import typenames

typenames(int)
#> 'int'
typenames(dict[str, typing.Any])
#> 'dict[str, Any]'
typenames(str | int)
#> 'str | int'
typenames(typing.Optional[str])
#> 'Optional[str]'

Why use this library?

String representations of Python type objects, type aliases, and special typing forms are inconsistent and often verbose. Here are some comparisons using default settings against built-in string representations:

Input With str(...) With typenames(...)
int <class 'int'> int
list <class 'list'> list
typing.Optional[int] typing.Optional[int] Optional[int]
collections.abc.Iterator[typing.Any] collections.abc.Iterator[typing.Any] Iterator[Any]
typing.Literal[MyEnum.NAME] typing.Literal[<MyEnum.NAME: 'value'>] Literal[MyEnum.NAME]

typenames also has handy configurable functionality, such as:

  • Forcing standardization on | operator union syntax (e.g., Union[int, str] to int | str) or vice versa
  • Forcing standardization on | operator optional syntax (e.g., Optional[int] to int | None) or vice versa
  • Forcing standardization on standard collection types for generics (e.g., List[int] to list[int]) or vice versa
  • Controlling exactly which module names to remove using regex patterns.

No need for string manipulation to get what you want!

Installation

typenames is available on PyPI:

pip install typenames

It is also available on conda-forge:

conda install typenames --channel conda-forge

Basic Usage

The main way to use the library is the typenames function. Calling it on a type annotation renders a string representation:

import collections.abc
import typing
from typenames import typenames

typenames(int)
#> 'int'
typenames(typing.Optional[str])
#> 'Optional[str]'
typenames(collections.abc.Callable[[int], tuple[str, ...]])
#> 'Callable[[int], tuple[str, ...]]

Under the hood, typenames parses a type annotation as a tree structure. If you need to see the parsed tree, use the parse_type_tree function to return the root node. You can get the rendered string representation by calling str(...) on root node.

import typing
from typenames import parse_type_tree

tree = parse_type_tree(typing.Union[typing.Any, list[typing.Any]])
tree
#> <GenericNode typing.Union[<TypeNode typing.Any>, <GenericNode <class 'list'>[<TypeNode typing.Any>]>]>
str(tree)
#> 'Union[Any, list[Any]]'

Configurable options

All configuration options can be passed as keyword arguments to either the typenames or parse_type_tree functions.

Union Syntax (union_syntax)

This option controls how unions are rendered. It supports both the typing.Union special form and the | operator (bitwise or) syntax from PEP 604. Valid options are defined by the enum UnionSyntax and include:

  • "as_given" (default): render the union as it is given without changing syntax.
  • "or_operator": render all type unions using the | operator.
  • "special_form": render all type unions using the typing.Union special form.

Optional Syntax (optional_syntax)

This option controls how optional types are rendered. It supports both the typing.Optional special form and the | operator (bitwise or) syntax from PEP 604. Valid options are defined by the enum OptionalSyntax and include:

  • "as_given" (default): render the optional type as it is given without changing syntax
  • "or_operator": render all optional types using the | operator
  • "union_special_form": render all optional types using the typing.Optional special form
  • "optional_special_form": render all optional types using the typing.Optional special form

Standard Collection Syntax (standard_collection_syntax)

Default value changed in v2.0.0

This option controls how parameterized standard collection generic types are rendered. It supports both the typing module's generic aliases (e.g., typing.List[...]) and the standard class (e.g., list[...]) syntax from PEP 585. Valid options are defined by the enum StandardCollectionSyntax and include:

  • "standard_class" (default): render all parameterized standard collection generic types using their class
  • "as_given": render the parameterized generic type as it is given without changing syntax
  • "typing_module": render all parameterized standard collection generic types using the typing module's generic alias

Removing Module Names (remove_modules)

This option controls how module names are removed from the rendered output. It takes a list of inputs, which can either be a string of the module name or a re.Pattern regex pattern directly (the result of re.compile). String inputs are templated into the following regex pattern:

module: str  # Given module name
re.compile(r"^{}\.".format(module.replace(".", r"\.")))

Note that module names are removed in the given order, so having entries that are submodules of other entries can potentially lead to the wrong behavior. You can either order them from higher-depth to lower-depth, or directly provide a compiled pattern with optional groups. For example, the pattern re.compile(r"^collections\.(abc\.)?") will match both "collections." and "collections.abc.".

The default list of module names include the standard library modules relevant to PEP 585 plus types and typing. It can be accessed at DEFAULT_REMOVE_MODULES.

DEFAULT_REMOVE_MODULES: List[Union[str, re.Pattern]] = [
    "__main__",
    "builtins",
    re.compile(r"^collections\.(abc\.)?"),
    "contextlib",
    "re",
    "types",
    "typing",
]

If you are trying to add additional modules to this option (rather than overriding the defaults), the easiest way to do so is to concatenate with the default list:

from typing import Optional
from typenames import typenames, DEFAULT_REMOVE_MODULES, BaseNode

# Default removals
typenames(Optional[BaseNode])
#> 'Optional[typenames.BaseNode]'

# Replace default with 'typenames'
typenames(Optional[BaseNode], remove_modules=["typenames"])
#> 'typing.Optional[BaseNode]'

# Extend default with 'typenames'
typenames(
    Optional[BaseNode],
    remove_modules=DEFAULT_REMOVE_MODULES + ["typenames"],
)
#> 'Optional[BaseNode]'

To remove all module names, you can use REMOVE_ALL_MODULES, which contains the pattern re.compile(r"^(<?\w+>?\.)+").

Annotated (include_extras)

This option controls whether to render Annotated and the extra metadata. typing.Annotated is a typing special form introduced in Python 3.9 and originally specified by PEP 593. Many libraries like Pydantic, FastAPI, and Typer use it to attach metadata to type annotations that are used at runtime.

By default, typenames will not render Annotated and extra metadata. Set include_extras=True to render them.

from typing import Annotated
from typenames import typenames

typenames(Annotated[int, "some metadata"])
#> 'int'
typenames(Annotated[int, "some metadata"], include_extras=True)
#> "Annotated[int, 'some metadata']"

Reproducible examples created by reprexlite.

Metadata

Release files for typenames 2.1.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 typenames 2.1.0
File Size Uploaded
typenames-2.1.0.tar.gz 160.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for typenames 2.1.0
File Interpreter ABI Platform
typenames-2.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 171.2 kB

Release files / typenames-2.1.0.tar.gz

Download URL typenames-2.1.0.tar.gz
Size 160.2 kB
Tags Source
SHA-256 checksum
How to use checksums
af231a91e8c377a5497693944d604865164adaf8754d17f521e61b0fbb1f6bf9
BLAKE2b-256 checksum
How to use checksums
eae343295dabe364f88d764be3595e942cb129469a99361a1af8fc77039912e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.8

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 Sep 15, 2025.

Transparency log

Release files / typenames-2.1.0-py3-none-any.whl

Download URL typenames-2.1.0-py3-none-any.whl
Size 11.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
34616136b4d6b92ef598fd5a2d2524506ef437489c71d1305e805046c41dd07d
BLAKE2b-256 checksum
How to use checksums
5d775a1219258adf0b217e8f3d1df84847073580d9d304e6fba77d03fb4fe733
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.8

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 Sep 15, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

2.1.0 This release

2 release files

2.0.0

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

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