{"id":16853728,"url":"https://github.com/abersheeran/typeddict","last_synced_at":"2025-04-05T10:43:35.538Z","repository":{"id":50318150,"uuid":"513977688","full_name":"abersheeran/typeddict","owner":"abersheeran","description":"Use `TypedDict` replace pydantic definitions.","archived":false,"fork":false,"pushed_at":"2024-04-25T10:34:25.000Z","size":41,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-28T19:07:35.107Z","etag":null,"topics":["pydantic","typeddict"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abersheeran.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":["https://donate.aber.sh/"]}},"created_at":"2022-07-14T16:44:40.000Z","updated_at":"2024-04-25T10:34:25.000Z","dependencies_parsed_at":"2024-10-13T13:53:03.611Z","dependency_job_id":"db95b2e3-f62d-4635-aabf-9ff5426f37b9","html_url":"https://github.com/abersheeran/typeddict","commit_stats":{"total_commits":13,"total_committers":1,"mean_commits":13.0,"dds":0.0,"last_synced_commit":"8ae3f1155fabfdde8680b0d30d2c1c658c367941"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abersheeran%2Ftypeddict","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abersheeran%2Ftypeddict/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abersheeran%2Ftypeddict/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abersheeran%2Ftypeddict/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abersheeran","download_url":"https://codeload.github.com/abersheeran/typeddict/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247325648,"owners_count":20920713,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pydantic","typeddict"],"created_at":"2024-10-13T13:53:01.496Z","updated_at":"2025-04-05T10:43:35.505Z","avatar_url":"https://github.com/abersheeran.png","language":"Python","funding_links":["https://donate.aber.sh/"],"categories":[],"sub_categories":[],"readme":"# TypedDict\n\nUse `TypedDict` replace [pydantic](https://pydantic-docs.helpmanual.io/) definitions.\n\n## Why?\n\n```python\nfrom pydantic import BaseModel\n\n\nclass User(BaseModel):\n    name: str\n    age: int = Field(default=0, ge=0)\n    email: Optional[str]\n\n\nuser: User = {\"name\": \"John\", \"age\": 30}  # Type check, error!\nprint(repr(user))\n```\n\nIn 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`.\n\n```python\nclass Message(BaseModel):\n    message: str\n\n\n@routes.http.post(\"/user\")\nasync def create_user(\n    ...\n) -\u003e Annotated[Message, JSONResponse[200, {}, Message]]:\n    ...\n    return {\"message\": \"Created successfully!\"}\n```\n\n## Usage\n\nUse `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).\n\n```python\nfrom typing_extensions import Annotated, NotRequired, TypedDict\n\nimport typeddict\nfrom typeddict import Extra, Metadata\n\n\nclass User(TypedDict):\n    name: str\n    age: Annotated[int, Metadata(default=0), Extra(ge=0)]\n    email: NotRequired[Annotated[str, Extra(min_length=5, max_length=100)]]\n\n\nclass Book(TypedDict):\n    author: NotRequired[User]\n\n\nuser: User = {\"name\": \"John\", \"age\": 30}  # Type check, pass!\nprint(repr(user))\n\n# Then use it in fastapi / index.py or other frameworks\nUserModel = typeddict.to_pydantic(User)\nprint(repr(UserModel.__signature__))\nprint(repr(UserModel.parse_obj(user)))\n\nbook: Book = {\"author\": user}  # Type check, pass!\nprint(repr(book))\n\n# Then use it in fastapi / index.py or other frameworks\nBookModel = typeddict.to_pydantic(Book)\nprint(repr(BookModel.__signature__))\nprint(repr(BookModel.parse_obj(book)))\n```\n\n### `cast`\n\nSometimes you may not need a pydantic model, you can directly use typeddict to parse the data.\n\n```python\nimport typeddict\n\n\nclass User(TypedDict):\n    name: str\n    age: Annotated[int, Metadata(default=0), Extra(ge=0)]\n    email: NotRequired[Annotated[str, Extra(min_length=5, max_length=100)]]\n\n\nuser = typeddict.cast(User, {\"name\": \"John\", \"age\": 30, \"unused-info\": \".....\"})\nprint(repr(user))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabersheeran%2Ftypeddict","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabersheeran%2Ftypeddict","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabersheeran%2Ftypeddict/lists"}