Basically, the fact that it works does not mean it works well, and I don't recommend anyone going in this other direction unless they understand what they are getting into.
Curious what limitations there are on static type checking. It seems like a matter of your IDE setup
> My own experience is that the DX with "real" TypeScript is much, much better than JavaScript with JSDoc
I agree with the DX point. I would just point out that if you're using JSDoc and getting intellisense from it, you are using TypeScript
More broadly, this is the default behavior of JS even without JSDoc blocks, and it ought to be the default behavior everywhere, including TS. I'm not alone in this sentiment, but it's incredibly contentious. There's been an open GH issue about it with hundreds of replies for years. I have no idea why they can't just pick a different shortcut for viewing types and call it a day. They'd be doing the entire ecosystem a favor.
Just use TypeScript.
Best thing for me was not removing the code transformation (convert ts to js), but separate runtime code with documentation code, like the types. Gives you much more clear insight that the types you write to describe what you expect the type will be is not forced on runtime, but is just for you as developer to know it. And when you validate the input is the right type, it is much more clear that it is the runtime type validation.
You can still use JSDoc in your typescript files, but why do you want to do that? There is no reason to do that.
So using JSDoc or Type Annotation, both works the same, same benefits, it is only personal preferences. Both have its pros and cons. For me the JSDoc has more benefits. Some other people prefer annotations. But there is not 1 that is better in controlling the types, has more options. (Also the enum can be done if you are using JSDoc, but is a little different)
JSDoc is more than type annotations. I use it for method and parameter descriptions, deprecation notices, inline examples, etc even in TS files.
You should occasionally look at the build artifacts of your framework but also ask yourself whether it is worth it to write code that may not represent what actually ends up being executed.
Lately I just use vite with no starter template but with web components and css modules. It at least feels more convenient than using any framework or library.
Doesn't this describe every programming language?
When you write C, you are technically not writing machine code.
Even when you write JavaScript, what actually gets executed is V8 bytecode and/or machine code (depending on whether the JIT fires).
I think the point I'm trying to make is that this can be confusing or even dangerous especially for new developers. It just doesn't hurt to actually look at the Vite plugins transforming it all to understand it instead of making assumptions if we work with it on the daily.
And I don't know about you, but I occasionally do open compiled ELF files in a hex editor and I certainly did at first when I was learning more. That's a good practice also.
Occasionally, I have to remember that JavaScript has no types at runtime but it's surprisingly not that often.
However I have been in a few situations at work where all of a sudden we did have issues that required us to dig deeper. There were also some bundling related issues that caused problems in production deployments. At that point many co workers had no idea how to even approach it to be honest.
(asking to learn)
I've even used Proxies directly to implement some reactivity before. However as for the "declarative" parts, I think it's just a little bit of a different way to work but you get used to it and imo it pays off. Knowing the web APIs should be a requirement anyway and it doesn't hurt to work with them directly as much as possible.
npm displays packages with bundled TypeScript declarations https://github.blog/changelog/2020-12-16-npm-displays-packag...
JSDoc-typed node modules require special configuration in consumers to be useful https://github.com/microsoft/TypeScript/issues/19145
Then, paradoxically, with no error checking at runtime, it becomes fully possible for JS code to call into TS code in a way that breaks the shit out of the TS compiler's assumptions. In philosophy then TS and JS are as incompatible as GPL and EULA
Sure, you can check if they gave you a string instead of a number. But if you receive an array of nested objects, are you going to traverse the whole graph and check every property? If the caller gives you a callback, do you check if it returns the correct value? If that callback itself returns a function, do you check that function's return type too? And will you check these things at every single function boundary?
This kind of paranoid runtime type-checking would completely dominate the code, and nobody does it. Many invariants which exist at compile-time cannot be meaningfully checked at runtime, even if you wanted to. All you can do is offer a type-safe interface, trust your callers to respect it, and check for a few common mistakes at the boundary. You cannot protect your code against other code calling it incorrectly, and in practice nobody does. This is equally true for JS and TS.
However, if your point is that Typescript can lull people into a false sense of safety, then sure, I take your point. You have to understand where type assertions are coming into play, and if that's obscured then the type safety can be illusory. The benefits of Typescript require you to make sure that the runtime inputs to your program are sufficiently validated.
If it's a service, yes, and that's true no matter what technology the service is using. If it's a library, no, because...
> and if you write type assertions without ensuring that the assertions are accurate, then that's on you, not Typescript.
That's on whoever is using the library, not the library author. If the library author provides type definitions, and you as the consumer choose to ignore them, then it's on you.
Usually there's little if any protection against a JS caller providing wrong-type args to TS functions.
I'm also not sure we're actually disagreeing on anything, so perhaps my reply was pointless. I agree that if you mix JS and TS in the way you describe, you'll have problems. My reply was just to say "yes, and that's not really Typescript's fault", but perhaps you weren't implying that to begin with.
* I'm aware that you can't run Typescript directly, but I hope my point here is clear... you're running a program that wasn't type-checked by TS.
If you write a C library, nothing stops someone from writing an assembly-language program that calls functions in your library with the wrong types.
To bridge runtime and compile time (as your application will likely get some external data) you've got to use a proper parser such as zod[1] or if you want to stretch it even further effect-schema[2].
[1] https://zod.dev/
A bonus of this approach is that it clearly delineates what type information is available at runtime, vs what type information is just a comment. (especially useful when working with serialized data).
I also like that it generally means all of the preconditions and postconditions for functions are in a single place (both the prose and the technical information are in the JSDoc comment), keeping the code itself low-noise and boiled down to its essence, and providing a natural place to write example inputs and outputs to guide usage.
As for generic types, I use them extensively, and this is made less verbose e.g. on function calls by using an @type annotation on the function which accepts a TypeScript signature without needing separate @template + @param annotations.
It's awesome stuff, and I'm happy that TypeScript works so well with JSDoc!
Also, you can use both (if that's what you prefer).