Apologies if this has already been asked/solved - I can't figure out exactly what this is called so it's very difficult to search for.
I'm writing a simple strongly typed dependency system, based on function closures. I have a decorator function that has this typing:
# This is a stand-in for a full class implementation that has a __call__ method matching
# Callable[P, Awaitable[R]] - I'm just omitting it for brevity
type CallableObject[**P, R] = Callable[P, Awaitable[R]]
def dependency[**P, R](*args: P.args, **kwargs: P.kwargs) -> Callable[
[Callable[P, Awaitable[R]] | Callable[P, R]], CallableObject
]:
...
This works to a degree, but, I want to transform the arguments in P to also accept functions that return the arguments type or an Awaitable of that type. For example:
def one() -> int:
return 1
def two() -> int:
return 2
@dependency()
def three(one: int, two: int) -> int:
return one + two
# I want the decorated three to have this signature
def decorated_three(one: int | Callable[..., Awaitable[int] | int], two: int | Callable[..., Awaitable[int] | int]) -> int:
...
Essentially, I want to apply a mapping to every arg and kwarg in P that transforms it into P | Callable[..., Awaitable[P] | P]. Is this possible with the current grammar?
As a reference, I wrote an example that does what I'm attempting to do in typescript, where you can unpack what they call "type tuples" using the keyof syntax to mutate their values:
function dependency<P extends unknown[], R>(wrap: (...args: P) => R): (...args: {[V in keyof P]: P[V] | ((...args: any) => P[V] | Promise<P[V]>)}) => R {
return wrap as any
}
function one(): number { return 1 }
function two(): number { return 2 }
function three(one: number, two: number): number { return one + two }
// Has type: const decorated_three: (one: number | ((...args: any) => number | Promise<number>), two: number | ((...args: any) => number | Promise<number>)) => number;
const decorated_three = dependency(three)
(Playground where you can see / verify the typing works as expected)
Apologies for dragging in another type system/language - I'm just looking for the python equivalent (if it exists).
Appreciate the help in advance. If this is a duplicate, please close it and mark it with the correct issue - I just couldn't find it 😅
Apologies if this has already been asked/solved - I can't figure out exactly what this is called so it's very difficult to search for.
I'm writing a simple strongly typed dependency system, based on function closures. I have a decorator function that has this typing:
This works to a degree, but, I want to transform the arguments in
Pto also accept functions that return the arguments type or anAwaitableof that type. For example:Essentially, I want to apply a mapping to every arg and kwarg in
Pthat transforms it intoP | Callable[..., Awaitable[P] | P]. Is this possible with the current grammar?As a reference, I wrote an example that does what I'm attempting to do in typescript, where you can unpack what they call "type tuples" using the
keyofsyntax to mutate their values:(Playground where you can see / verify the typing works as expected)
Apologies for dragging in another type system/language - I'm just looking for the python equivalent (if it exists).
Appreciate the help in advance. If this is a duplicate, please close it and mark it with the correct issue - I just couldn't find it 😅