TypeScript for Pythonistas
medium.com
medium.com
It is a tradeoff though, there is one thing I tend to like better about nominative typing that isn't quite as easy with structural typing, and that's reflection. Sure, you can query about keys/fields in the instance itself, but you can't match it back to say a type annotation on a class very easily. Type guards (for things like overloads) can also be a bit weird to write, for instance you can't really do an "instanceof" because that information is lost at run time, so instead you write these functions that can return "T is Cat", and that function will check for something like if the instance has a "meow" function attached. Once you get used to it it's basically fine, but it can be a bit cumbersome sometimes.
And while there’s no instanceof that works for non-class structured data like this, (and it wouldn’t be particularly necessary in TS only codebases), even if you were in a mixed repo where there’s a bunch of untyped JS, you could fairly easily create a wrapper with the same behavior of instanceof even without resorting to classes by using symbols. So long as the data is nonmutable, you can effectively get the equivalent of an O(1) instanceof check in JS code, but with a bit more ceremony.
Isn’t the normal way to do this in TS to use discriminated unions, where you just store the type right there on the object as a string (perhaps in a key called “tag” or “type”)? I love discriminated unions, and needing to explicitly carry around that discriminator is a bit awkward coming from, say, OCaml, but it’s still my default way of modeling most things in TS.
So TypeScript is to JavaScript as XSD is to XML.
The analogy isn't perfect, but it's close. The analogy doesn't seem to work for DOM composition at all.
I mentioned TypeScript used for productivity. What that means is not reducing code authorship time, but instead reducing time everywhere else such as maintenance and refactoring time. The common use cases are restricting primitives to unions of accept values where appropriate, defining functions to use required typed arguments and typed output, and defining all objects against respective static types. You want your editor to yell at you as you are making code changes when things don't fit as you intended opposed to finding these problems at execution time.
I wrote-up a high-level comparison between the type systems of TypeScript and mypy here that might be of interest to type enthusiasts
Sometimes hints and intellisense are 90% of what you need from a type system.
Compared to TS, are Python typings as second class, uncomfortable, often overly verbose as I remember them to be? Have things improved?
ETA: and/or that talking about C++ templates as "typed" one way or another is problematic, given that they're a part of the type system.
* https://en.wikipedia.org/wiki/Structural_type_system
* https://en.wikipedia.org/wiki/Duck_typing
These are non=competing qualities. In duck typing there is no actual code interpretation, as in run time evaluation. Instead instances are compared against a type definition looking for conformance and presumed good so long as the compiler does not see a misalignment to the type definition. This is generally good enough when both the type definitions and the code instances are static qualities in the code, but exceptions can occur if there are dynamic mutations the compiler does not recognize such as extending extending a base type with a dynamic quality.
Structural typing uses structures to define relationships and those relationships become points of evaluation to determine subsets. Relational evaluation is most useful in tree models such as DOM (HTML, XML), file system, certain database models like DB2, some machine learning models. The useful qualities of relationship evaluation are that you can evaluate correctness via a path, as in navigation from one node to another, and determine if a code instance is properly composed.
There is some overlap between those two type definitions in TypeScript in that an object interface can be defined from various smaller interfaces. This is mostly done for code reuse, but benefits composition.