https://github.com/abersheeran/typeddict
Use `TypedDict` replace pydantic definitions.
https://github.com/abersheeran/typeddict
pydantic typeddict
Last synced: over 1 year ago
JSON representation
Use `TypedDict` replace pydantic definitions.
- Host: GitHub
- URL: https://github.com/abersheeran/typeddict
- Owner: abersheeran
- License: apache-2.0
- Created: 2022-07-14T16:44:40.000Z (about 4 years ago)
- Default Branch: master
- Last Pushed: 2024-04-25T10:34:25.000Z (over 2 years ago)
- Last Synced: 2025-03-28T19:07:35.107Z (over 1 year ago)
- Topics: pydantic, typeddict
- Language: Python
- Homepage:
- Size: 40 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# TypedDict
Use `TypedDict` replace [pydantic](https://pydantic-docs.helpmanual.io/) definitions.
## Why?
```python
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int = Field(default=0, ge=0)
email: Optional[str]
user: User = {"name": "John", "age": 30} # Type check, error!
print(repr(user))
```
In index.py or other framework, maybe you write the following code. And then got an type check error in `Annotated[Message, ...]`, because the type of `{"message": "..."}` is not `Message`.
```python
class Message(BaseModel):
message: str
@routes.http.post("/user")
async def create_user(
...
) -> Annotated[Message, JSONResponse[200, {}, Message]]:
...
return {"message": "Created successfully!"}
```
## Usage
Use `Annotated` to provide extra information to `pydantic.Field`. Other than that, everything conforms to the general usage of `TypedDict`. Using `to_pydantic` will create a semantically equivalent pydantic model. You can use it in frameworks like [index.py](https://github.com/index-py/index.py) / [fastapi](https://fastapi.tiangolo.com/) / [xpresso](https://github.com/adriangb/xpresso).
```python
from typing_extensions import Annotated, NotRequired, TypedDict
import typeddict
from typeddict import Extra, Metadata
class User(TypedDict):
name: str
age: Annotated[int, Metadata(default=0), Extra(ge=0)]
email: NotRequired[Annotated[str, Extra(min_length=5, max_length=100)]]
class Book(TypedDict):
author: NotRequired[User]
user: User = {"name": "John", "age": 30} # Type check, pass!
print(repr(user))
# Then use it in fastapi / index.py or other frameworks
UserModel = typeddict.to_pydantic(User)
print(repr(UserModel.__signature__))
print(repr(UserModel.parse_obj(user)))
book: Book = {"author": user} # Type check, pass!
print(repr(book))
# Then use it in fastapi / index.py or other frameworks
BookModel = typeddict.to_pydantic(Book)
print(repr(BookModel.__signature__))
print(repr(BookModel.parse_obj(book)))
```
### `cast`
Sometimes you may not need a pydantic model, you can directly use typeddict to parse the data.
```python
import typeddict
class User(TypedDict):
name: str
age: Annotated[int, Metadata(default=0), Extra(ge=0)]
email: NotRequired[Annotated[str, Extra(min_length=5, max_length=100)]]
user = typeddict.cast(User, {"name": "John", "age": 30, "unused-info": "....."})
print(repr(user))
```