[TypeScript] does not actually ensure that the data you are manipulating corresponds to the type that you have declared to represent it. For example, the data might contain additional fields or even incorrect values for declared types.
This is only a problem if you are mixing untyped code with typed code, isn't it? Like when you are parsing JSON, you need to do typechecking right then, rather than just using an "any" type. The only other situation I have run into this in practice with TypeScript is when I'm using a library that has slightly misdefined types.
> This is only a problem if you are mixing untyped code with typed code, isn't it?
I find it a bit strange that people talk about this as "only a problem", as though it was some weird niche edge case and not an ever-present issue. The written-in-plain-JS ecosystem completely dwarfs the written-in-TypeScript one; unless you're doing something rather trivial you're quite likely to end up depending on a library that barely had the shape of its objects in mind during development, with typings (if they're even present) that were contributed by someone that's almost definitely not the actual library author.
Of course, if you're competent enough you can correct typings and always remember to run runtime checks on data that doesn't come from you and so on. But it's too easy for a beginner to fall into traps like mishandling data that comes from a dependency (especially when it's buggy/ostensibly has typings) - in my opinion, there should be a first-party compiler/linter option to enforce checks on any `any`.
You don't have to depend on badly-written untyped third-party libraries, just because there are a lot of them out there. Many projects and companies will avoid doing so. This is especially reasonable if your comparison is switching to a language like Rust; there are probably fewer third-party libraries available in Rust overall than there are libraries with accurate TypeScript definitions available.
"Badly-written" is of course subjective, but as for untyped/loosely typed I think it's a bit difficult to claim that people are avoiding using them when (for example) the typings for an obviously popular library like Express are chock-full of `any` types[0]. Including several (like request bodies) that should instead be `unknown`. I'm sorry but it's rather naïve to expect a beginner to TypeScript, especially one that's coming from JS, to not trip up at all using typings like that and a compiler/language spec that implicitly casts things declared as `any`.
No, nominal types are extremely useful to ensure the correctness of your software.
You can define a function to receive a FirstName and LastName instead of passing strings so you cannot accidentally mix up the parameters for example.
There are several techniques to approximate nominal typing in typescript (https://medium.com/better-programming/nominal-typescript-eee... for example) and there is an open issue https://github.com/Microsoft/Typescript/issues/202 but it’s still not being considered for implementation as far as I remember.
Not sure if this is a place to ask this but if someone does not have experience working with Javascript, they might have trouble reasoning about this code:
Dog and Person are structurally the same so you can assign a person to a dog and vice versa. But that's just how structural typing works and as a user of TypeScript I haven't run into a case where this'd be an issue.
I worked on a web based editor. A library would give us a range to highlight, in 1-based coordinates. The editor control was 0-based. As you can imagine it was easy to forget to translate back and forth in one path or another. In a strongly typed language I would simply define two Range types and the compiler would eliminate the mistake. I assumed Typescript could help me in the same way but it allowed the two types to be interchanged silently because they had the same structure. Perhaps I was holding it wrong?
Typescript has two hacks that help with mixing of similar data and introduce somewhat-nominal typing - branding and flavoring [1]. Also see smart constructors [2] for more functional approach.
No[1], TypeScript is unsound in many ways. Most of them are intentional trade-offs to catch as many bugs as possible while not being too restrictive/allowing most JavaScript code to be annotated.
> The only other situation I have run into this in practice with TypeScript is when I'm using a library that has slightly misdefined types.
Unfortunately there's no way to know which libraries have defined their types correctly, so you end up having to check the types you get back from every library you use.
This is only a problem if you are mixing untyped code with typed code, isn't it? Like when you are parsing JSON, you need to do typechecking right then, rather than just using an "any" type. The only other situation I have run into this in practice with TypeScript is when I'm using a library that has slightly misdefined types.