Issue 1:
First Check

I added a very descriptive title to this issue.

I used the GitHub search to find a similar issue and didn't find it.

I searched the FastAPI documentation, with the integrated search.

I already searched in Google "How to X in FastAPI" and didn't find any information.

I already read and followed all the tutorial in the docs and didn't find an answer.

I already checked if it is not related to FastAPI but to Pydantic.

I already checked if it is not related to FastAPI but to Swagger UI.

I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

I commit to help with one of those options 👆

Example Code

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class MyBaseModel(BaseModel):
def __hash__(self): # make hashable BaseModel subclass
return hash((type(self),) + tuple(self.__dict__.values()))

class NestedItems(MyBaseModel):
name: str

class Items(MyBaseModel):
items: set[NestedItems]

@app.post("/offers/")
async def create_items(items: Items):
return items

This can be tested with the following command:

uvicorn mre:app --reload &
curl -X 'POST' \
'http://127.0.0.1:8000/offers/' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"items": [
{
"name": "string"
}
]
}'

Description

The following command triggers the error TypeError: unhashable type: 'dict'.

It works if I replace NestedItems by a simple str.

It works if I replace set by a simple list.

Operating System

Linux

Operating System Details

Ubuntu 22.04

FastAPI Version

0.86.0

Python Version

3.11.0

Additional Context

No response

Issue 2:
First Check

I added a very descriptive title to this issue.

I used the GitHub search to find a similar issue and didn't find it.

I searched the FastAPI documentation, with the integrated search.

I already searched in Google "How to X in FastAPI" and didn't find any information.

I already read and followed all the tutorial in the docs and didn't find an answer.

I already checked if it is not related to FastAPI but to Pydantic.

I already checked if it is not related to FastAPI but to Swagger UI.

I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

I commit to help with one of those options 👆

Example Code

from fastapi import Depends, FastAPI

app = FastAPI()

def dependency() -> int:
return 99

@app.get("/")
def read_root(my_int: int = Depends(dependency)):
return {"an_int": my_int}

Description

Is there any reason that Depends does not use generics to automatically type hint the injected dependency?

Currently, the Depends function's return is typed as Any:

def Depends( # noqa: N802
dependency: Optional[Callable[..., Any]] = None, *, use_cache: bool = True
) -> Any:
return params.Depends(dependency=dependency, use_cache=use_cache)

This leads to a lot of duplicate code writing the type hints when defining an endpoint, for example:

@router.post("/", response_model=FileRead)
async def upload_file(
*,
file: UploadFile,
session: Session = Depends(get_session),
user: OIDCUser = Depends(get_user),
file_manager: AsnycBaseFileManager = Depends(get_file_manager),
) -> File:
...

@router.get("/content/{file_id}")
async def get_file_content(
*,
file_id: int,
session: Session = Depends(get_session),
file_manager: AsyncBaseFileManager = Depends(get_file_manager),
) -> StreamingResponse:
...

There is also room for human error if you write the wrong type hint, with no static type checking tools being able to prevent this.

It is possible to use Generics to properly type hint the Depends function:

T = TypeVar("T")

def Depends( # noqa: N802
dependency: Optional[Callable[..., T]] = None, *, use_cache: bool = True
) -> T:
return params.Depends(dependency=dependency, use_cache=use_cache)

This leads to automatically having the correct type hints:

Is there a reason Depends explicitly returns Any, instead of an unbounded TypeVar? If not I am happy to PR this and PR documentation if necessary.

Wanted Solution

T = TypeVar("T")

def Depends( # noqa: N802
dependency: Optional[Callable[..., T]] = None, *, use_cache: bool = True
) -> T:
return params.Depends(dependency=dependency, use_cache=use_cache)

Wanted Code

from fastapi import Depends, FastAPI

app = FastAPI()

def dependency() -> int:
return 99

@app.get("/")
def read_root(my_int = Depends(dependency)):
return {"an_int": my_int}

Alternatives

No response

Operating System

Windows

Operating System Details

No response

FastAPI Version

0.75.2

Python Version

3.9.12

Additional Context

No response