Top
Best
New

Posted by culi 12/14/2025

JSDoc is TypeScript(culi.bearblog.dev)
208 points | 275 commentspage 2
g947o 12/14/2025|
I work in a codebase that unfortunately does not support TypeScript. I use JSDoc extensively, although not with type check enabled (due to various limitations). I also work on other projects with TypeScript. My own experience is that the DX with "real" TypeScript is much, much better than JavaScript with JSDoc, without question. JavaScript with JSDoc is much more verbose, with a lot of limitations when types get long or complex compared to TypeScript. The official TypeScript language service also does not provide the same level of support in very subtle ways.

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.

culi 12/14/2025|
> although not with type check enabled (due to various limitations)

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

g947o 12/15/2025||
Not a limitation in language service, but an issue with the codebase itself -- legacy codebase with a lot of missing/incorrect typing from upstream JavaScript code (owned by other teams), making it practically impossible to actually run type check.
CSSer 12/15/2025||
> For packages typed with JSDoc, CTRL/CMD clicking on a function will take you to actual code rather than a type declarations file. I much prefer this experience as a dev.

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.

auggierose 12/15/2025||
Been there, tried that. When starting to write JavaScript in anger 3 or 4 years ago, I started out with JSDoc, because my impression was also, hey, that is like TypeScript, but closer to the metal and maybe with less magic. A few months in I realised that TypeScript is just a better and more well-rounded implementation of what JSDoc has to offer (I don't remember now, but there were annoying things that you would expect would work in JSDoc, but didn't quite).

Just use TypeScript.

w3news 12/15/2025||
Thanks, I use JSDoc for several years, and also validate it with Typescript. So I just write plain Javascript with JSDoc, with no build step. Typescript only validates the types, and not transforming the code. Did you also know that you can import Typescript types/interfaces in JSDoc? So for me typescript is not a language anymore, I use only the tool to validate the types.

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)

supernes 12/15/2025|
> You can still use JSDoc in your typescript files, but why do you want to do that?

JSDoc is more than type annotations. I use it for method and parameter descriptions, deprecation notices, inline examples, etc even in TS files.

sureglymop 12/14/2025||
A somewhat related thing programmers must understand is that whether you write typescript, JSX, .astro or .svelte files, you are technically not writing JavaScript.

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.

umanwizard 12/14/2025||
> ask yourself whether it is worth it to write code that may not represent what actually ends up being executed.

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).

sureglymop 12/14/2025|||
That's correct, however I would say there is a small difference in that most of this code still seems just like JavaScript, sometimes it even feels as though it is JavaScript running in the same context when it then gets compiled to run on server/client.

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.

vlovich123 12/14/2025|||
Yeah it’s a silly line of reasoning. The transformations of TS -> JS are a lot smaller and simpler than C-> asm / machine code; it’s basically just removing type annotations. Now minification and optimization can make the output a lot more terse, but that can be done for JS too. And it’s not as complicated and detached from the source as an optimizing compiler is.
sureglymop 12/14/2025||
Let's not act like it's the same thing. I'm not strictly talking about just Typescript, I'm saying that if you work with these technologies every day it would be wise to go look at their Vite plugins to see how they transform your code and be sure to understand it. It's nice to have magic but it's nicer to use the magic if we have demystified it first.

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.

wvenable 12/14/2025|||
This seems like an issue but in all my practical experience it really isn't. TypeScript becomes JavaScript with the types removed. Then you tree-shake, minify, and whatever is executed is no where near what you actually wrote but at the same it totally is the same because that's no different than any other compilation process.

Occasionally, I have to remember that JavaScript has no types at runtime but it's surprisingly not that often.

sureglymop 12/14/2025||
I mean what makes it more acceptable is that you have HMR and instant preview during development. So, all the transformations and bundling aside, you do see how it runs during development.

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.

wvenable 12/14/2025||
I've had similar experiences with compiled languages in one form or another throughout my career as well. I don't think JavaScript is particularly special that we need to call it out for things like TypeScript, minification, or bundling.
kaufmann 12/14/2025||
Aren't you loosing a lot of the declarative features like signals or similar, when you do your projects without those frameworks?

(asking to learn)

sureglymop 12/14/2025||
Somewhat. I could still use framework agnostic state management libraries/patterns and most are (e.g. svelte signals, jotai, zustand, etc.).

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.

jcbhmr 12/15/2025||
JSDoc works great for buildless application setups! One downside is that if you publish a library to npm you still need a build step to generate .d.ts files from your JSDoc type annotations so that npm shows a "TS" badge on the npm package page. This also seems to apply to VSCode's intellisense which keeps trying to poke you to "try to install @types/jsdoc-typed-package to get type information". Other JS ecosystem tooling also doesn't seem to process JSDoc types at all such as jsdocs.io or tsdocs.dev. So for libraries we're stuck with .d.ts generation via "tsc --allowJs --checkJs --declaration ..." even if it's all JS.

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

conartist6 12/14/2025||
I still think that JS is very much not TS. Most TS code assumes you never need to check for errors because the type checker proves they can't happen.

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

sethaurus 12/14/2025||
It doesn't matter if a library is written in TS or JS; you cannot meaningfully protect against other code calling you incorrectly.

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.

md224 12/14/2025|||
Writing a Typescript program that takes external input but has no runtime error checking is already a mistake, though. Dealing with external input requires type assertions (since Typescript doesn't know what the program is getting at compile-time) and if you write type assertions without ensuring that the assertions are accurate, then that's on you, not Typescript.

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.

billyp-rva 12/14/2025|||
> Writing a Typescript program that takes external input but has no runtime error checking is already a mistake, though.

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.

conartist6 12/14/2025|||
TS certainly thinks of external input as a boundary requiring safety, but usually that would mean form input or CLI args parsing or something.

Usually there's little if any protection against a JS caller providing wrong-type args to TS functions.

md224 12/14/2025|||
Sure, but if the caller is Javascript then you're running Javascript, not Typescript*, so it makes sense that you're not going to get type safety.

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.

conartist6 12/15/2025||
I don't think we're disagreeing either. I didn't mean to suggest that it was Typescript's fault, just that the relationship between TS and JS in theory is something like "TS is a superset of JS" but once you get down to the practice of writing idiomatic reusable code it's more like TS and JS are fully different languages.
umanwizard 12/14/2025|||
Something similar is true for most statically typed languages.

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.

epolanski 12/14/2025||
The type checker can only prove what is known at compile time and only if you're disciplined.

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/

[2] https://effect.website/docs/schema/introduction/

girvo 12/14/2025||
I’m currently in love with Arktype, and as it supports Standard Schema it plugs into most places that can take Zod schemas too :)

https://arktype.io/

epolanski 12/14/2025||
That's a validator, not a proper parser, no?
culi 12/15/2025|||
What's the difference here? I've only used Zod but I typically think of Zod as a runtime validation library. AFAIK arktype is a full-featured replacement for Zod
girvo 12/15/2025|||
I don't think I understand the difference you're drawing on here? It parses data and validates its structure, and is a replacement for all my uses of Zod?
auxiliarymoose 12/14/2025||
This is how I develop web software, and I've found it productive and maintainable.

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!

Lorin 12/15/2025||
Not when the TS team refuses to fix long standing issues preventing JSDOC from operating properly in VSC, for example https://github.com/microsoft/TypeScript/issues/16665
n2d4 12/15/2025|
To be honest, I find Ryan Cavanaugh's argument against this quite convincing. It's weird to have something documented if you import the .ts file, but not if you import a .d.ts generated from it. If you want to show the value of the default argument of a function, you should probably just add it to the doc comment — not the type.
Lorin 12/15/2025||
The argument is that it doesn't surface the default written within the jsdoc block comment even when provided by the developer.
Brysonbw 12/15/2025|
I'm a big advocate for explicit type annotations in code. Likewise, either or is good with me. However, these days I lean towards using JSDoc only because I prefer not to add typescript lib and an additional build step just to get type safety in a project.

Also, you can use both (if that's what you prefer).

More comments...