You're blaming TypeScript for self-inflicted wounds.
Don't blame the type system that you banished (with `as unknown as T`) for not catching you; or for some React library having bugs, e.g. an incorrect interface; for not defining types and Pikachu-facing when types are `undefined`. These traumas are fixed by using TypeScript, not ignoring it.
These issues don't exist in languages that aren't built on a marsh.
More specifically though, I feel like the way javascript libraries with types work is often painful to use and that's why people use TS's escape hatches, whereas the same thing doesn't happen in languages where everything is built on types from the get go.
The same friction is true for example of using C libraries from other languages.
The rest of the world is an equally muddy marsh. C++: static_cast, C: void-pointers and unions, java/c#: casting back from (object) or IAbstractWidget.
If anything, typescript has the most expressive, accurate and powerful type system of the lot, letting you be a lot more precise in your generics and then get the exact type back in your callback, rather than some abstract IWidget that needs to be cast back to the more concrete class. The structural typing also makes it much easier to be lax and let the type engine deduce correctness, rather than manually casting things around.
C is famously unsafe. But in Java/C#, you do have runtime type safety. You can't just cast something to something else and call it a day. In the worst case, you'll get an exception telling you that this does not work. In TypeScript, the "cast" succeeds, but then 200 lines later, you get some weird runtime error like "does not exist on type undefined" which doesn't tell you at all what the source of the error is.
In TypeScript, a variable can have a different runtime type from its declared type entirely, that's just not true for many other languages
I'm not sure about the CLR, but the JVM has no type safety whatsoever. Java the language does, but all of that goes away once you are in the JVM bytecode.
This is just partially true (or completely untrue in the mathematical sense since your statement is "_no_ type safety _whatsoever_" :P ). The whole purpose of the bytecode verifier is to ensure that the bytecode accesses objects according to their known type and this is enforced at classloading time. I think you meant type erasure which is related - generic types do not exist on the bytecode level, their type parameters are treated as Object. This does not violate the bytecode verifier's static guarantees of memory safety (since those Objects will be cast and the cast will be verified at runtime), but indeed, it is not a 100% mapping of the Java types - nevertheless, it is still a mapping and it is typed, just on a reduced subset.
"don't exist in languages that aren't built on a marsh"
Sure. Last time I checked, JavaScript is the language that actually powers the web. If you can get a language that isn't built on a marsh along with all the libraries to run the web, I'll switch in a second.
In other words, the criticism is simply irrelevant. If it works, it works. We don't talk about technologies that don't exist.
Not run on the web, "to run the web". Maybe someday WASM will be complete enough to actually run the web, but JavaScript is what we have right now and it's done a pretty okay job so far.
> These issues don't exist in languages that aren't built on a marsh.
Unsafe casts exist in almost any GCed strongly typed language. You can unsafe things even in Rust, if you want to. Author of this code has deliberately made a choice to circumvent language's limitation and forgo it's guarantees. We have been doing it since undefined behaviour in C, how is that Typescript's fault?
Totally! I really wonder what these libraries people are complaining about that have such bad type definitions. In my experience TS definitions on the average NPM package are generally fairly decent.
Well, the reality of the situation still is that there are libraries with incorrect or low quality typings that blow up in your face. Me using TypeScript will not make that library better, but this problem is still the daily reality of using TypeScript. It's not the fault of TS, but still a pain you encounter when working with it.
I haven't worked with a language where you can statically cast invalid types that easily since C, a language not exactly famously known for its safety.
There's a reason `as unknown as T` exists, and it's JavaScript's highly dynamic nature and absence of runtime types (ignoring classes and primitives). It's an escape hatch that is needed sometimes. Sure, within your own codebase everything will be fine if you forbid its use, but every library call is an API boundary that you potentially have to check types for. That's just not great DX
I haven't worked with a language where you can statically cast invalid types that easily since C, a language not exactly famously known for its safety.
But it’s not the same situation at all, is it? If you make an invalid cast in C, your program will crash or behave in bizarre ways.
If you make an invalid cast in TS, that doesn’t affect the JS code at all. The results will be consistent and perfectly well-defined. (It probably won’t do what you wanted, of course, but you can’t have everything.)
TS is much more like Java than it is like C (but with a much nicer type system than either).
Meh, in Java (afaik) you'll get exceptions when you cast incorrectly. In JS and C, it just gets allowed and you get some runtime error later on and have to make your way back to find your incorrect cast.
Don't blame the type system that you banished (with `as unknown as T`) for not catching you; or for some React library having bugs, e.g. an incorrect interface; for not defining types and Pikachu-facing when types are `undefined`. These traumas are fixed by using TypeScript, not ignoring it.