Search code examples
pythonpython-typingmypypydantic

Type check Pydantic BaseModel as type hint with mypy


I am using pydantic to create models and apply data validation. Simultaneously I'd like to use these models as type hints (because they contain more information than simply saying dict). Killing two birds with one stone :)

from pydantic import BaseModel, StrictStr, StrictInt

class Person(BaseModel):
    name: StrictStr
    age: StrictInt


def my_func(user: Person) -> None:
    print(user["name"])

However, mypy does not properly parse the models, and gives this error message:
error: Value of type "Person" is not indexable [index]

I'd like mypy to type check the pydantic BaseModel and not give an error.

Optionally I could create a TypedDict and use that as type hint, but then I lose the pydantic strict functionality.


Solution

  • So the short answer is that you don't get to use the [] operator on instances of a class derived from the Pydantic BaseModel.

    Since you created the class you can simply get the Person's name with person.name, so your function would look like this:

     def my_func(user: Person) -> None:
        print(user.name)
    

    If you need to use your Person instance as a dict you can do it, and there are two methods.

    1. pass the person instance to the dict constructor like dict(person)
    2. you can call the .dict() method of the person instance like: person.dict() This will allow you to do a "partial" class even.

    To learn more check out the docs


    Since you use mypy and seem to be a beginner with Pydantic I'm guessing you don't have the mypy plugin for Pydantic set up. You don't need to install anything, as it comes with the Pydantic package.

    If you use a pyproject.toml file (and I believe you should), you add this to the end to enable it.

    [tool.mypy]
    plugins = [
      "pydantic.mypy"
    ]
    

    To learn more about the plugin, you can take a look at its docs