Typing Untyped Third-Party Dependencies in My Project

I have a project that depends on several untyped third-party dependencies, and without types, the IDE and the type checker can’t help me. I don’t plan to type them completely, just the API surface that I’m using in my project. For this, the first solution that comes to my mind is creating thin wrappers. Take the following example, assuming foobar is a third-party untyped library.

# typed_foobar.py
if TYPE_CHECKING:
    def baz(a: str, b: int) -> bool: ...
    
    class FooBar:
        a: str
        b: int
else:
    from foobar import baz as baz, FooBar as FooBar

Then in my codebase, I import typed_foobar instead of foobar:

from .typed_foobar import baz, FooBar

But this approach is still a bit subpar to me. I have to create modules and import from them solely for type hints. I now wonder if there’s a way for me to provide my own type stubs for these untyped libraries in a way that doesn’t lock me into one type checker or IDE, although I can manage editing a config or two. Something like telling my IDE and type checker that they can look into typings/foobar.pyi for foobar type hints, allowing me to continue importing foobar without a wrapper in between.

Write the stubs, put them in a directory, configure the checkers to look there. I usually put them in typings since Pyright looks there by default (so I avoid configuring it at all), and then set mypy_path = "$MYPY_CONFIG_FILE_DIR/typings" for Mypy.

5 Likes

I think this approach is the best way for you to provide type-hints to this untyped module, as adding hints in some stubs/ would have users trying to clone / uses you project need to get access to the stubs/ folder, an if that is in some local folder, and can’t be imported from some location, users would need to change code. If however you have the stub in you project, users can clone / install / use the project without having to use the stubs.

This is exactly what I wanted, thank you!