This at least is being solved in Python: https://www.python.org/dev/peps/pep-0563/
> inline interfaces
Typed dicts in 3.8 look pretty similar at cursory glance https://www.python.org/dev/peps/pep-0589/
I'll definitely play around with it more!
This at least is being solved in Python: https://www.python.org/dev/peps/pep-0563/
> inline interfaces
Typed dicts in 3.8 look pretty similar at cursory glance https://www.python.org/dev/peps/pep-0589/
I'll definitely play around with it more!
// typescript
let t: {a: string[], b: number} | [string, string]
# python 3.8
from typing import TypedDict, Tuple, Union
class SomeTypedDict(TypedDict):
a: List[str]
b: Union[float, int]
t: Union[SomeTypedDict, Tuple[str, str]]
I had to google a bunch to figure out how to write the Python version, whereas the typescript one was completely natural to write. It takes one line and requires no imports. The interface is inlined. All of this also makes it more readable when you come across it eg. in an IDE tooltip. @dataclasses.dataclass # or @attr.s
class MyStruct:
a: List[str]
b: int|float
t: MyStruct|Tuple[str,str]
But MyStruct will be an actual object that can be manipulated as an object. And if you want to accept any object that fits that interface, instead of just instances of MyStruct, class MyStructTmpl(Protocol):
a: List[str]
b: int|float
Then def f(thing: MyStructTmpl|Tuple[str,str]) -> bool:
return True
f(MyStruct(a=['a'], b=2))
would typecheck.In JS having the typed-dict type makes sense because you're often working with arbitrary objects with who knows what attributes, but in python that isn't the case. There's fairly succinct and powerful tools (now, anyway) to define record types.
I'm also not onboard the "it's a code smell, it doesn't matter" train. IMO if python adopted the typescript typing syntax we'd all be better for it.
I also forgot to mention the atrocious typing syntax for functions. Once again, typescript is a lot more succint and readable.
I more or less agree with this, but then again, IMO you should be isolating the less controlled code behind a controlled api. And the marginal value of converting `_ConvertQueryResultDictToQueryResult(qr: Dict[str, Any]) -> QueryResult` to something that uses a typeddict instead (which may not be possible, since that function is probably generic) is low.
> I'm also not onboard the "it's a code smell, it doesn't matter" train.
Emphatically, this isn't what I'm saying. What I will say is that ergonomics encourage certain methods of development. From experience, I'm strongly against the pattern of using a dict as a weak struct. The best comparison I can give is tuple -> namedtuple -> attrs. Namedtuple has absolutely valid uses (when you need tuple semantics, usually for backwards compatibility). But people often use it for any record type, because it's easy and familiar. Dataclasses are usually better, and I'd be happier (and the average python code would be better) if the friction to add a dataclass was lower than the friction to add a namedtuple.
Similarly, if the friction to use a dict in place of an object is much lower, people will be encouraged to use dicts in place of objects. This isn't a good thing. That doesn't mean that we absolutely shouldn't try to improve ergonomics across the board, but I'm a strong believer that the language should make doing the right thing easier than doing the wrong thing, and this is often (but not always!) the wrong thing.
Maybe both should be in the global namespace...