Description
Currently, constructors (__init__
) take *Like
types (eg, StringLike = Union[str, StringExpr]
), which was needed to allow literal value shorthand in constructor calls. However, the @init_in_parent
provides a translation later that actually narrows the types, __init__
still accepts the *Like
types on a call, but internally (seen by __init__
) is all *Expr
types.
Prior to #96, all constructor parameters should be re-mapped via self.param = self.Parameter(...)
and given an explicit type. #96 changes the constructors to infer parameter types based on typing annotations, so for example if we had param
as part of the constructor argument list, we could directly use self.param = param
. The downside is that param
is of type *Like
(from the constructor) instead of the more narrow and accurate *Expr
(returned by self.Parameter
).
This causes a mild issue with generators, since they should only take *Expr
types. The current workaround is to expand generators to also take the castable-types in addition to the *Expr
types - which isn't completely accurate, but continues to provides convenient lightweight syntax in exchange for a bit of leakiness in the type checking of an advanced feature.
Properly typing init_in_parent
Ideally, one solution would be to define the init_in_parent
decorator type, such that the __init__
can be properly defined in terms of *Expr
type, and the decorator would provide a wrapped function that takes the *Like
type. The problem is that functions (Callables) have contravariant types for the argument list, so it can't capture the ConstraintExpr[...] type parameters (for example, it doesn't accept BoolExpr in place of the ConstraintExpr[...] pattern).
Additionally, having an *Expr in the type signature of __init__
, even if the decorator is properly typed, may be confusing, since users might see the __init__
type signature and wonder why a literal type is allowed. However, the @init_in_parent
decorator could signpost that, and since the behavior is consistent it's only one additional learning curve item.