DEV Community

Discussion on: JavaScript First, Then TypeScript

 
peerreynders profile image
peerreynders • Edited

I have demonstrated fully that TypeScript does bring value to the table using a 3-line example.

Value that can be delivered with static type analysis alone. No language required.

The point is that Flow delivers exactly the same value, according to some people at a higher level of quality, without proclaiming itself as a language but simply as a “static type checker”.

So:

Betting on TypeScript tooling as a static type checker (TS-as-a-devtool) is where the current value is.

Using it as a language is risky especially for features that are not on the current list of TC39 proposals.

Thread Thread
 
webjose profile image
José Pablo Ramírez Vargas • Edited

Ok, so clearly you want to continue arguing. The problem I have, and I say this without trying to be antagonist, is that you are like Alexa:

Me: "Alexa, isn't this a TypeScript-exclusive feature?"
Alexa: "Facebook uses Flow for type checking."

If you can actually stay on topic, I'll be glad to continue the discussion. If you, however, are incapable of reasoning within the boundaries of the topic, I'll just make myself scarce. I am not, and will not be, diverted by off-topic subjects. I am also not interested in other people's words. I'm interested in your own and my own. We are the ones in this discussion, not others. All your quoting is irrelevant to me because I make my own mind and not comply with others just because of their alleged reputations.

I'll start: I love, as many of us do, VS Code. Flow and VS Code are not a thing. Therefore, it is not going to be a thing for us to move to Flow. Let's just drop Flow. Let's talk about things that could actually happen.

Let's discuss the very important matter: TypeScript exists, is a language and comes with tsc from Microsoft. tsc is not very performant. Is this a "language" feature? It is not. Why? Anyone could make a better transpiler and the language itself would be unaffected. Agreed? If yes, you must also agree by extension, that tsc !== TypeScript. Yes? No? Discuss, but stay on topic. I am not interested in stories about the history of pictographic communications in caves found in the Middle East that date from 15.000 BC.

Thread Thread
 
peerreynders profile image
peerreynders • Edited

Anyone could make a better transpiler and the language itself would be unaffected.

Faster transpilers have already been delivered.

As far as I'm aware tsc (and LSP) is the only tool capable of type checking the TypeScript syntax and nobody is working on changing that.

And as to your example:

// @ts-check
/** @param {number | void } value */
function doSomething(value) {
    return value * 6;
}
Enter fullscreen mode Exit fullscreen mode

TS playground

  • Same type checking benefit
  • No TypeScript syntax (or language) in value space where the JavaScript exists.
  • Only TypeScript annotations to be processed by tsc
  • The TypeScript syntax used here applies entirely to type space

variable declaration space
type declaration space

Fixed:

// @ts-check
/** @param {number | void} [value] */
function doSomething(value) {
    return (value ? value : 1) * 6;
}
Enter fullscreen mode Exit fullscreen mode

I love, as many of us do, VS Code. Flow and VS Code are not a thing. Therefore, it is not going to be a thing for us to move to Flow.

Which just emphasizes again that TypeScript adoption/popularity is primarily about developer convenience rather than safe types.

Thread Thread
 
webjose profile image
José Pablo Ramírez Vargas

Great! We are getting somewhere now. Tell me: Is the benefit coming from JsDoc, or Typescript enforcing JsDoc? Because in jsfiddle.net:

Image description

I get no feedback.

Thread Thread
 
peerreynders profile image
peerreynders • Edited
  • JSDoc simply acts as a conveyance for TypeScript's type declaration syntax
  • Either tsc or LSP parse the type syntax inside the JSDoc annotation to fill in the "type space gaps" in the JavaScript code.
  • Together with the information in the value space JavaScript, tsc or LSP determine whether the code type checks.
  • The programming language is still just JavaScript.
Thread Thread
 
webjose profile image
José Pablo Ramírez Vargas • Edited

Ok, yes. I see your point more clearly now. Because JsDoc goes into comments, there's no stripping to do. That is most certainly a clear advantage, probably the greatest advantage over TypeScript, no doubt.

So, we have two options for type safety: One that uses comments, and one that doesn't, and people say the latter can go away. I guess it is only logical. Unless, that is, that TypeScript (the latter) has something else in its favor, and there is.

TypeScript can bring new JavaScript features to life faster. Yes, you have already argued about how that could be problematic. Still, it is a feature that only TypeScript provides. I believe in the democratic process of every developer to choose their tooling, and I truly believe that this is one of those cases. It is no small thing, in my opinion. Yes, there will be people that say this doesn't justify the grievances of transpiling. I get that.

At this point, I must admit you have me half-convinced. See? All that ranting about Flow and all those quoting got you nowhere with me, but your succinct demonstration got me thinking!

I could probably ask you about the capabilities of JsDoc, but I suppose that I should just investigate that on my own to determine whether or not I should opt for JsDoc. For example, it is very difficult for me (or impossible, really) to imagine I can define the types I need for an entire project with just comments. I am a back-end developer, so my experience with JavaScript is not very extensive. My main concern right now is: Can I define the data models of an entire application in JsDoc, centrally in one location and use the definitions in the rest of the project?

UPDATE: Question: Is JsDoc a thing by itself? Or must it always piggyback ride on TypeScript? I must confess I'm confused about this topic for the first time. I am concluding that in VS Code all that is needed is the language server. If this is true, and JsDoc can provide an alternative to at least most of TypeScript features, it is something I must learn ASAP. The one thing that would seriously worry me is not having a CI/CD method of making sure developers did their work of honoring all of the Intellisense feedback.

Thread Thread
 
artxe2 profile image
Yeom suyun

This thread is quite interesting.
Here is my personal opinion, TypeScript is definitely prone to adding aggressive syntax sugar due to its compilation-based nature.
And these are a kind of auto code.
However, the basic JS syntax has been sufficient since ES6.
Some features may require polyfills, but if you only use the basic JavaScript syntax, TypeScript will simply perform type checking, which means that you don't even need to copy my source code from the src folder to the dist folder.
Of course, TypeScript provides a watch feature, so in many cases these limitations will not be felt significantly. But it's not zero.
Perhaps the biggest advantage of JSDoc is that you can see the actual implementation code using VSCE's ctrl + left click while using the library.
This is not possible with js or compiled ts.
Perhaps the JSDoc example in my Stackblitz will answer your questions.

Thread Thread
 
peerreynders profile image
peerreynders • Edited

Is JsDoc a thing by itself?

Yes but the intent is only to document, not type check (e.g. like Doxygen).

Or must it always piggyback ride on TypeScript?

That is why I go out of my way to use the term TS JSDoc when referring to applying TypeScript types to JavaScript code via JSDoc. I suppose the choice of using JSDoc was influenced by the fact that Google's Closure Compiler already used JSDoc to carry type hints.

I must confess I'm confused about this topic for the first time.

A large segment of the TS user community is. Back in May it became very clear that many did not understand the tool chain they work with day-to-day when there was a social media uproar against SvelteKit moving to JSDoc when in fact the team:

  • wasn't giving up type checking (they were just moving it later into the development workflow)
  • was still going to supply their user community with verified TypeScript types.

I am concluding that in VS Code all that is needed is the language server.

It is the defacto choice but lots of editors/IDEs are capable of supporting the language server protocol (IntelliJ WebStorm, neo/vim, etc.).

If this is true, and JsDoc can provide an alternative to at least most of TypeScript features, it is something I must learn ASAP.

Be advised, in my experience using TS JSDoc effectively requires a higher level of tooling knowledge/competence than just using TS syntax in an LSP supported editor. So typically it makes sense to spend ones time first with the pure TS syntax because it (at least on the surface) seems more familiar coming from the likes of C#/Java.

But TypeScript's type manipulation syntax (and the way it extracts information from value space into type space) can take some time getting used to.

That isn't to say the TS JSDoc isn't without its annoyances.

Many simply prefer their types conflated with the implementation because that is what they are familiar with from other languages (Haskell/Elm converted me to separating types from implementation) and they resent having to type more (Typing is not a programming bottleneck).

Having to juggle between undefined and void in the type declarations until it finally works is tedious (tsc seems to randomly shallow undefined from sum types otherwise). And in case you didn't notice I couldn't get value ?? 1 to type check in your example leading me to use value ? value : 1 instead; so you are sometimes forced to write your code a certain way for the type checking to work as intended.

would seriously worry me is not having a CI/CD method

That is what tsc -noEmit is used for. For whole project type checking there is no way to get around tsc right now but if it is confined to CI/CD it isn't a big issue.

For example, it is very difficult for me (or impossible, really) to imagine I can define the types I need for an entire project with just comments.

In practice you don't.

You will still have *.ts files (see this comment) to hold shared or complex types but only for declaring types or extracting type information from JS files (another complaint against TS JSDoc is the frequent separation of TS types and JS implementation 🤷). In JS files you can import these types for reference.

Can I define the data models of an entire application in JsDoc, centrally in one location and use the definitions in the rest of the project.

You could simply define all the types with TypeScript syntax in *.ts files and just import those types into the JS files.

I am a back-end developer

The thing is in back-end code there is little incentive to use TS JSDoc (just stick to writing a JavaScript with types TS flavour to be on the safe side). It can be useful when you identify code on the hot path that is less than optimal (due to the TS transform) allowing you to take direct control over the exact JS runtime code.

Using JS can be a lot more critical on front end packages where either size matters or where the TypeScript syntax creates a barrier to using a certain parser for some niche code analysis tool or bespoke compiler.

Thread Thread
 
somedood profile image
Basti Ortiz

This thread of argumentation has really piqued my interest. I am already well aware of tsserver's built-in support for JSDoc annotations, but you have convinced me to more seriously consider it as a means to further minimize the TypeScript surface in my project (particularly for very simple type annotations in function parameters). More complex typings would, of course, still remain in .ts files, but I am quite attracted to the idea of moving more TypeScript syntax into JSDoc instead.

This is not to say that TypeScript is evil. I intend to minimize the TypeScript surface to better emphasize the sufficiency of language semantics when it comes to .js files—specifically the OCaml-like assertion that "pure type inference is sufficient".

Thread Thread
 
peerreynders profile image
peerreynders

ngl TS JSDoc can be a bit painful, especially in the beginning and too painful for many to even stick with it for any length of time, mostly because esbuild sidelined the constant need for tsc anyway.

That said with TS JSDoc your premise becomes “JavaScript first, then Types”.

Thread Thread
 
somedood profile image
Basti Ortiz

ngl TS JSDoc can be a bit painful

I'd say it's only painful when trying to jam a bunch of TypeScript syntax into it. At that point, we may as well just use TypeScript for that, which is syntactically superior over the hacky shoehorning of TypeScript syntax into JavaScript comments. For simpler annotations of function parameters, however, TS JSDoc is fine with me.

That said with TS JSDoc your premise becomes “JavaScript first, then Types”.

You know, this is actually pretty good. Perhaps that is my ultimate end goal. 🤔

Thread Thread
 
webjose profile image
José Pablo Ramírez Vargas

Thank you, @peerreynders for the details. So we are kind in the middle of things where there is no definite alternative to TypeScript.

My take from your explanation is, and correct any details if I miss any:

  1. JsDoc is dependant on TypeScript, and that's why you refer to the solution as "TS JsDoc".
  2. JsDoc cannot be used to document an entire project, so .d.ts files are still needed.
  3. There is no alternative in the CI/CD: tsc is king right now in this arena.
  4. If we can, we can maximize REPL-like experiences by avoiding TS in web projects. Not that it is super bad right now, since esbuild does a tremendous job of transpiling TS code. It just doesn't type-check.

I guess, then, that fighting over TypeScript at this point in time is of no consequence: There's no alternative. There should be no feud until the day comes where an alternative is available. Then we can be at each others' throats. 😄

Thread Thread
 
peerreynders profile image
peerreynders • Edited

JsDoc cannot be used to document an entire project, so .d.ts files are still needed.

In a TS JSDoc project *.d.ts and *.ts play different roles:

  • The project consumes *.d.ts files that provide the missing type information for dependencies, either supplied or DIY (handwritten types).
  • The project declares it's (internal and) published types in any number of *.ts files.
  • tsc can then be configured to output a *.d.ts for consumers of the project

There should be no feud

There is no feud. Just a case of many TS developers dismissing TS JSDoc out hand mostly based on developer convenience, additional learning curve and confusion about the difference between JSDoc and TS JSDoc.

Thread Thread
 
logic_bender profile image
logic bender • Edited

@peerreynders I think you make some fair points about TS, but your comparison between dialyzer and TS is entirely a reach. First of all, dialyzer gives you some type safety to Erlang but doesn't extend the language, nor does it let you annotate or operate on types (the language already does that). A fairer comparison would be between Liquid Haskell and TS. Because both are extensions to the language, they are not just a "fancy linter" but an actual extension of the language. That is the case because Typescript enhances Javascript not just with type-safety but with the ability to annotate types and also with features that let you catch another whole class of type errors using, for instance, dependent types. But even if there were no dependent types, TS brings the benefits of a fully-fledged type system because that is what TS is, i.e., a programming language with a static type system.

I understand your argument revolves around typescript's main focus, not being type safety but developer convenience. Although it is a valid point, it's a partial truth. Typescript chose to have unsoundness to make its adoption more accessible, but no language is entirely sound. For example, Haskell is unsound concerning FFI and undefined, or C# is unsound concerning null or typecasting. Thus, it is better to talk of soundness for a set of runtime type errors. In that sense, a language can be more type-safe than others, or in other words, it can be more sound than others, but that doesn't mean the lesser one does not have type-safety. So, type-safety is a critical characteristic that Typescript brings to the table. Still, you have to be extra careful when using its unsound aspects (as in other type-safe languages).

Finally, though you bring up some valid points, I think saying TS is not its language (like Rescript, Purescript, ELM, etc...) is missing the main point of why one should use (TS, Hegel, and Flow) and their difference to JSDocs or a linter.

UPDATE
To be fair, I am being a bit hyperbolic about dialyzer and TS; I think those tools are comparable regarding type checking, although they serve different purposes. But the main point is that a linter does not extend the capability of the language, which is why not every type-checker is a linter.

Thread Thread
 
peerreynders profile image
peerreynders • Edited

your comparison between dialyzer and TS is entirely a reach.

It was made to reinforce the idea of using TS tooling for the purpose of static analysis in reference to this tweet, i.e. TS-as-a-devtool rather than TS-as-a-language.

linter does not extend the capability of the language,

In what way does TypeScript extend the capability of JavaScript? JavaScript can be used in ways that can't be statically typed in TypeScript (the point of The Trouble with TypeScript). TypeScript may be a superset to JavaScript in terms of developer features but TypeScript can only express a subset of all valid JavaScript code.

I think saying TS is not its language is missing the main point of why one should use and their difference to JSDocs or a linter.

The discussion was around the primarily value proposition behind the TS tooling ecosystem. In particular:

Betting on TypeScript tooling as a static type checker (TS-as-a-devtool) is where the current value is.

Using it as a language is risky especially for features that are not on the current list of TC39 proposals.

Leveraging TS language features that aren't (soon becoming) standard in JS can easily make portions of that ecosystem inaccessible. The example I chose:

Relying on TypeScript specific features (e.g. decorators) essentially blocks that build time optimization.

Using decorators would mean foregoing esbuild (and therefore Vite) altogether or essentially crippling that development setup:

“The solution was to get a plugin that negated all of the performance gained by ignoring TypeScript. The plugin runs each typescript file through tsc before passing it to esbuild.”

Once one accepts that the primary value of TS comes from adding types to JavaScript the next step is to acknowledge that the same benefit can be derived (albeit with a bit more pain) by simply using JavaScript and augmenting it with TS types via JSDoc (which is different from JSDoc for documentation).

In the past few months a lot of the "you can't do this with TS JSDoc" statements have been proven wrong even though some of the solutions are ugly or downright flaky.

Preact switched to TS JSDoc ~2020 and SvelteKit in May 2023; so even if it's somewhat tedious it must cover all the bases.

It is this approach of using TS-as-a-devtool (rather than TS-as-a-language) that describes using TS as a "type linter" or more formally as a static analysis tool,