Using typing.NewType for Opaque Data Types in Python Libraries
Library authors often need configuration objects that consumers can pass around but shouldn’t construct directly or poke at internals. In C, opaque types like FILE handle this cleanly via header typedefs, but Python’s classes expose their constructors by default — even private fields don’t stop callers from instantiating the class, and type checkers won’t flag it.
The pattern proposed is to combine typing.NewType with a private underlying class. The NewType becomes the public name used in annotations, the private class holds the actual fields, and a small set of public factory functions returns instances typed as the NewType. Callers get a name they can annotate against and constructors that express intent (shipFast, shipNormal), but no visibility into the underlying structure.
The payoff is API evolution: because consumers never touched the real class, its fields and constructor can be rewritten freely without breaking downstream code. NewType carries near-zero runtime overhead since it’s the same object as the wrapped type at runtime, with an optional type: ignore escape hatch for hot loops where even the wrapping call matters.
Read the full article
Continue reading at Hacker News →This is an AI-generated summary. Read the original for the full story.