Reputation: 47
I'm working on adding python type annotations to an existing codebase. I have a function that takes in a set of database IDs, checks if the user has permissions to view the underlying models, and then returns the list of models. The existing type annotations look something like:
AuthorizeableModel = TypeVar["ModelType", lower=HasAuthMixin]
def bulk_load_and_check_auth(model_ids: List[str]) -> List[AuthorizeableModel]:
# ...
This isn't wrapped in a class since this can be used to bulk fetch a heterogeneous list of models. However, the HasAuthMixin
type is pretty thin and oftentimes I need to do more complicated stuff with the return value of that function.
In typescript I could create a function signature like:
function bulkLoadAndCheckAuth<T extends AuthorizeableModel>(dbIds: Array<str>): List<T> {
// logic
and then I could specify the expected type of the function
const models = bulkLoadAndCheckAuth<MyModel>(idsList);
Is there any way to do something similar with python types?
Upvotes: 0
Views: 1151
Reputation: 3439
In Python generic type argument can be applied only in the case of classes.
However, classes can be callable, hence there is the following hack to achieve what you want:
AuthorizeableModel = TypeVar("AuthorizeableModel", bound=HasAuthMixin)
class _bulkLoadAndCheckAuthType:
def __call__(self, model_ids: list[str]) -> list[HasAuthMixin]:
...
def __getitem__(
self, _: type[AuthorizeableModel]
) -> Callable[[list[str]], list[AuthorizeableModel]]:
return self # type: ignore
bulk_load_and_check_type = _bulkLoadAndCheckAuthType()
models = bulk_load_and_check_type[MyModel](["id1", "id2"])
reveal_type(models) # Revealed type is "builtins.list[MyModel]
Upvotes: 1