Forward return type of injected dependencies with Depends()
See original GitHub issueFirst 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
"""
I have a dependency that specifies a return type, but that type is erased
when I inject it into an endpoint using `Depends()`
"""
from fastapi import FastAPI, Depends
app = FastAPI()
async def dependency() -> int:
return 0
@app.get("/")
async def root(dep = Depends(dependency)):
# Get mypy to emit the return type of the value returned by the dependency
reveal_type(dep) # Revealed type is "Any"
Description
When injecting dependency
it into my view function with Depends(dependency)
, the return type (int
) is erased and replaced with Any
.
This can be verified by running mypy
against my code sample above (reveal_type()
should cause mypy to emit the type it infers)
Wanted Solution
It would be great if the return type of dependency
were preserved, i.e.
@app.get("/")
async def root(dep = Depends(dependency)):
reveal_type(dep) # Revealed type is "int"
Depends is currently defined as:
def Depends(dependency: Optional[Callable[..., Any]] = None, *, use_cache: bool = True) -> Any:
I’m no expert on the Python type system or Mypy, but I think the following could get Mypy to correctly infer the return type of dependency
:
from typing import TypeVar, Awaitable, Union
T_ = TypeVar("T_")
MaybeAwaitable = Union[T_, Awaitable[T_]]
T = TypeVar("T")
def Depends(dependency: Optional[Callable[..., MaybeAwaitable[T]]] = None, *, use_cache: bool = True) -> T:
return params.Depends(dependency=dependency, use_cache=use_cache)
Wanted Code
"""
The return type of my dependency should be preserved
when injecting it with `Depends(dependency)`
"""
from fastapi import FastAPI, Depends
app = FastAPI()
async def dependency() -> int:
return 0
@app.get("/")
async def root(dep = Depends(dependency)):
reveal_type(dep) # Revealed type is "int"
Alternatives
No response
Operating System
macOS
Operating System Details
No response
FastAPI Version
0.75.0
Python Version
3.7.9
Additional Context
My current approach is to explicitly annotate my injected dependencies, but this is prone to error since Mypy doesn’t help catch these issues.
Consider:
from fastapi import FastAPI, Depends
app = FastAPI()
# Returns a different type now
async def dict_dependency() -> dict:
return {}
@app.get("/")
async def root(dict_dep: int = Depends(dict_dependency)):
# But Mypy doesn't catch the issue
reveal_type(dict_dep) # Revealed type is "int"
Issue Analytics
- State:
- Created a year ago
- Reactions:2
- Comments:14 (2 by maintainers)
Top Results From Across the Web
Advanced Dependencies - FastAPI
Let's imagine that we want to have a dependency that checks if the query parameter q contains some fixed content. But we want...
Read more >The Simplest Guide to FastAPI Dependency Injection using ...
Learn how to use FastAPI Dependency Injection using Depends keywords to handle dependencies in the form of dict, classes, global dependency.
Read more >python - Unable to inject dependencies to FastAPI endpoints
@lru_cache(max_size=1) def get_chords_service(): return ChordsService() @router.get("") def get_chords(chords_service: ChordsService=Depends( ...
Read more >Dependency injection in action - Angular
The useClass provider key lets you create and return a new instance of the specified class. You can use this type of provider...
Read more >Setting Up Dependency Injection with TypeScript in an Object ...
In general, the concept of a dependency depends on a context, but for simplicity, ... return randomSource.random() * (max - min) + min;...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Is there not a middle ground where we can forward the return type if we are 100% sure, and otherwise return Any? It’s a massive shame to discard this completely because of how useful it would be for FastAPI users? Something like:
After some analysis i think it’s not possible to add correct type annotation to
Depends
mostly because of context manager-like dependencies that are usually annotated withIterable[T]
orGenerator[T, None, None]
If we assume that all dependencies annotated with
Iterable[T]
returnT
would break dependencies that return iterable objects:Perhaps some context manager specific type annotations could be used to resolve problem with iterables and generators and wrap fastapi dependencies into
@contextlib.contextmanager
manually