3 ms·
Structural typing is really necessary in Typescript just because Javascript objects don't generally carry a class around (at least not if it's defined with the
by overgard 5y ago
Structural typing is really necessary in Typescript just because Javascript objects don't generally carry a class around (at least not if it's defined with the {} literal syntax). I find though, that now that I've used structural typing nominative typing is a lot more restrictive and I generally prefer the structural approach. It's especially nice with JSON objects coming from remote APIs.
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.
- 0xfffafaCrash 5y agoA lot of people don’t seem to be aware that there are a bunch of excellent runtime validation libraries that one can use to encode runtime validation checks which produce the typescript types for you (so you rarely have to write ”T is Cat” yourself where it is easy to introduce a false type) but instead can write (or even generate) trustworthy decoders that give you the types. There’s too many of these very-similar libraries to list but some of the more popular ones include io-ts, zod, purify-ts,and suretype. 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.
- akaptur 5y agoI didn't get into this in the blog post, but we use io-ts at Pilot, and we generate most of the codecs based on the type annotations on the Python side. It works reasonably well, although I think the io-ts syntax confuses people who are new to TypeScript.
- tshaddox 5y ago> 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 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.