If you're rabidly anti-TypeScript and think that us doing this vindicates your position, I'm about to disappoint you. If you're rabidly pro-TypeScript and think we're a bunch of luddite numpties, I'm about to disappoint you as well.
Firstly: we are not abandoning type safety or anything daft like that — we're just moving type declarations from .ts files to .js files with JSDoc annotations. As a user of Svelte, this won't affect your ability to use TypeScript with Svelte at all — functions exported from Svelte will still have all the same benefits of TypeScript that you're used to (typechecking, intellisense, inline documentation etc). Our commitment to TypeScript is stronger than ever (for an example of this, see https://svelte.dev/blog/zero-config-type-safety).
I _would_ say that this will result in no changes that are observable to users of the framework, but that's not quite true — it will result in smaller packages (no need to ship giant sourcemaps etc), and you'll be able to e.g. debug the framework by cmd-clicking on functions you import from `svelte` and its subpackages (instead of taking you to an unhelpful type declaration, it will take you to the actual source, which you'll be able to edit right inside `node_modules` to see changes happen). I expect this to lower the bar to contributing to the framework quite substantially, since you'll no longer need to a) figure out how to link the repo, b) run our build process in watch mode, and c) understand the mapping between source and dist code in order to see changes.
So this will ultimately benefit our users and contributors. But it will also benefit _us_, since we're often testing changes to the source code against sandbox projects, and this workflow is drastically nicer than dealing with build steps. We also eliminate an entire class of annoying papercuts that will be familiar to anyone who has worked with the uneven landscape of TypeScript tooling. The downside is that writing types in JSDoc isn't quite as nice as writing in TypeScript. It's a relatively small price to pay (though opinions on this do differ among the team - this is a regular source of lively debate).
We're doing this for practical reasons, not ideological ones — we've been building SvelteKit (as opposed to Svelte) this way for a long time and it's been miraculous for productivity.
I primarily coded in Python for 4 years. Then I founded a company that didn't need as much data science and my primary language switched to JavaScript (2 years) then TypeScript (4 years). Overall, I really like TypeScript. But I do absolutely miss being able to cmd + click into a function/class from an open source package and see the actual implementation and not just a type definition. This is probably the biggest day-to-day frustration I have with TS compared to JS and Python.
JavaScript Ecosystem itself.
It's incredible we do transpiration, minification, bundling to the same language the interpreter is going to read.
Because people want to follow in the footsteps of big projects that have gained specialized knowledge through experience.
It's also a really contrarian viewpoint about typescript which is really popular.
tbh, this seems pretty far out there. Sourcemap file size is a non-issue, they're not gigabytes, and editors like vscode now support going to the source definition for projects that support it. To completely switch over to js and then set types that way seems regressive. Just so that people can modify the source code directly a little bit easier? There are all kinds of tools ranging from ts-node-dev that make watching typescript files easy, with options to skip type checking for better speed. Honestly seems kind of backwards.
I really, really don't get the controversy here. JSDoc _is_ TypeScript, just with a syntax that's valid JavaScript (on account of it living in comments). This means it doesn't have to be built to run, but still gets all of the typing goodies regular TypeScript does. The end-user code authoring experience is the same or better.
> To completely switch over to js and then set types that way seems regressive.
"It's regressive to use a fully-JS TypeScript syntax instead of using dozens of tools on top of regular TypeScript to achieve the same outcome" is quite a spicy take.
Sure, by themselves, but replicate that across everyone repeatedly downloading the library in various build processess, in various projects and with different versions.
Sure, by itself a sourcemap might not add up to much. But then there is various projects with different versions, who download the library repeatedly in different build steps. Then it starts to add up both in bandwidth, and in storage taken.
Luckily, there are still package and library maintainers who care about making things less, instead of more, both in architectures and size.
> Just so that people can modify the source code directly a little bit easier?
This is a real thing that is useful to think about, how to make your software easier to change in the future, while just solving the current concern without over-engineering the solution.
I'll add that IntelliJ+Copilot makes writing solid JSDoc very fast and easy.
First, to ensure a focused discussion, I think it's a good idea to separate out TypeScript the transpiler, TypeScript the language, TypeScript the type-checker, and by extension, TypeScript 'types'.
Personally, I don't like transpilers. I never liked CoffeeScript and I hate not being able to see the 'actual' code when looking inside a Docker image in a K8s cluster. I also don't like using non-standard features in a language; I'd far rather live without something that is TS-specific, and if it turns out that this feature has legs, then just wait for it to be included in vanilla JS. (Not to mention that it smacks too much of vendor lock-in, for not much benefit.)
But I do get that this is to some extent because I'm primarily coding to Docker images, rather than multiple browsers. If I want to bump the version of Node to get some new feature, it's pretty easy. So I do recognise that for people working on the client side, where bundling and source maps and all that other chaos is the norm, then transpiliation is no big deal.
(Having said that, back in the day we all used to love that you could hack away on a web app using files on a file system, just loading HTML, JS, and CSS... It's a shame that we seem to have lost the 'vanilla first' approach to software, and leap to preprocessors for everything.)
Anyway... my first point is simply that TypeScript as a _transpiler_ doesn't have any appeal to me.
But I'm not about to throw the baby out with the bath water.
As with the original post, I love types! I think TS types are the best thing to happen in years. Where possible I like to use declaration files as the single source of truth (type first development). From there you can generate GraphQL and OpenAPI schemas, use them to drive contracts for implementation, share the files with other developers using other languages, and so on. And as with this post, I make the connection between the types in the declaration files and the code in the JS files, primarily through inference, and then as necessary through JSDoc.
As with many things, there is going to be a lot of personal preference to this. Since I like the way that Haskell puts type information on a separate line to the function that is being described, it's probably no surprise that I also find the JSDoc approach of putting the types in separately more intuitive.
And since it's easy to configure an editor/IDE to use TSC to lint and provide intellisense on JS files, you can get all of the advantages of TypeScript without having to transpile.
That seems like I pretty good deal to me!
Is it contrarian - yes - is it insane - no, not really.
Edit: the motivation seems to be to simplify processes - running TS files can be awkward, and cross importing is awkward. fwiw created my own tool for this ([url-redacted])
I think this is the critical piece not everyone understands. Under the covers, it's basically still Typescript (see https://www.typescriptlang.org/docs/handbook/intro-to-js-ts....). The major difference is that type information is specified in comments so that the source file is still valid JS and thus doesn't need a separate compilation step. There is not an exact parity between type info that can be specified with JSDoc and Typescript, but my understanding is that it's pretty close.
Any folks familiar with Flow (before Typescript essentially won out), Flow had something similar that was very nice, IMO better because it was the same Flow syntax, just wrapped in comments: https://flow.org/en/docs/types/comments/
FYI, you committed the wrong license file. The license file contains license text of a standard MIT License, but your project is licensed under Apache...
(and downsides not really, beyond it's pretty fresh so bug reports welcome)
Very rarely we find a case that we can't cover with JSDoc annotations, and most of the time it means the code could be refactored to be simpler.
I do this now for all my personal projects, in my opinion it's simpler, faster and closer to pure JS.
I regret every `infer` statement I've put in application code.
Grug phrased this elegantly:
I ask because for most of my projects there's at least some bundling going on, and in that case the added complexity of Typescript compilation is pretty minimal - with tools like Vite there is no added complexity, because JS and TS files are going down exactly the same pipeline, parsed by the same parser, etc. And I could get rid of the bundler, which would make some things simpler, but makes imports and deployment more complicated. For the scale of projects that I'm working on, bundling feels like necessary complexity.
I guess I'm trying to figure out if this is a useful form of minimalism for the sorts of projects I work on, or if this is the sort of thing that works for some projects but not others.
TS features don't need types to produce output[1] and this is supported by the compiler; it just doesn't have a CLI option.
Compiling without types is supported the compiler itself (this is what Babel does).
[1] Except const enum and export *
Can with JSDoc define types? And can you define generic types? To me that is the real power of TypeScript, being able to type every object you use.
But the one big annoyance is events - I've never found a satisfying way of writing a JSdoc that says what events a class emits, or what parameters the events have. Do you have a way of handling this?
Nowadays it's expected that you get software for free, and if you don't like it you have the moral right to complain at insane lengths at the maintainers of this software. Even if you don't agree with certain decisions (which in this case shouldn't even be the case), there's a way of going about things, you're dealing with people, not faceless corporations.
Typescript migration was on our road map, but when we dug into it, it didn't solve the biggest issue we had with Javascript, which forces the developer to be aware of various pitfalls. Because of that, we didn't feel that TypeScript solved enough of JavaScript's faults to warrant a migration.
I still think that TypeScript is great and has some of the best tooling I've had the pleasure of working with, but in our case we didn't feel that the added complexity was worth the trade off. JSDoc is "good enough", even though we've run into bugs with it on VS Code.
The latest I ran into, `Object.keys(x).length` appears to recalculate length on every call. There doesn't appear to be a fast (and idiomatic) way to get top level object size in Javascript without using a secondary incrementor.
We'll cut a preview release soon and would love help testing and feedback from folks that have given it a try.
In practice, what I’ve found is that the hassle of adding type assertions even if they’re correct nudges me to write worse code (“to appease the type checker”) in JS/Doc than it does in TypeScript syntax. I don’t think TypeScript syntax makes me feel more relaxed about writing unsafe type assertions, but I’m probably an outlier because I pretty much only do that when I’ve exhausted every other available/known approach.
/**
* @type {module:look/here~MyType}
*/
or TypeScript "JSDoc" imports like /**
* @type {typeof import("./look/here").MyType}
*/
or both?Being able to click through to the implementation in your ide is nice though, but can be solved by the ide.
Edit:
Here’s one example, you can define your routes in symfony using comments. Not only that, but it’s actually the officially recommended way of doing things. Absolute madness.
Smuggling pragmas in comment has a long and rich history. It’s literally the reason why json does not support comments.
> Reading about JSDoc gives me the same uneasy feeling, even if it’s not quite the same thing.
It’s not just “not quite the same thing”, it’s entirely unrelated in every way and shape. JSDoc does not affect the runtime behaviour of its code, or how that code interacts with other systems.
At the moment. You’ve literally just said yourself that there is a long history of smuggling code into comments. A few years down the line I don’t want to suddenly have the feature added and then have to be on the look out when I’m debugging a codebase for secret code in comments.
From the page you linked:
> Routes can be configured in YAML, XML, PHP or using attributes. All formats provide the same features and performance, so choose your favorite. Symfony recommends attributes because it's convenient to put the route and controller in the same place.
Attributes are not comments, they are an official structured way of handling metadata.
[1] https://www.php.net/manual/en/language.attributes.overview.p...
Docblock comments can also be inspected with reflection [3] but have a much looser syntax, so it was up to you to parse them. Where as you can create a new instance of an attribute directly from the reflection object [4]
In your example Symfony uses it to build up the list of HTTP routes by looking through all your controllers for #[Route] attributes. Generally that's done once and then cached, at least in production.
Personally I try to avoid using them, but they're definitely not comments. More like metadata you can attach to classes/methods/properties/parameters then use however you want.
[1]: https://www.php.net/manual/en/language.attributes.syntax.php
[2]: https://www.php.net/manual/en/reflectionclass.getattributes....
[3]: https://www.php.net/manual/en/reflectionclass.getdoccomment....
[4]: https://www.php.net/manual/en/reflectionattribute.newinstanc...
So comments that are code then.
Everyone can sit around going “This is not a pipe it’s a photo of a pipe or my perception of a photo of a pipe”. But if you did not have a sentence above your photo saying “This is not a pipe” or an arts teacher to tell you “this is not a pipe” and there was just a picture of a pipe on the page and someone pointed at it and said “can you tell me what that is?” You would say “why of course, it’s a pipe”. And then all of a sudden it started spouting water out of the end (let’s assume it was a GIF) then you can say “oh it looks like a pipe but it’s actually a water pistol masquerading as a pipe”. The fact that as a dev you have to constantly be on the look out for water pistols masquerading as pipes rather than having a clear distinction between pipes and water pistols is just a piss poor and easily avoidable design decision.
What you're thinking of in PHP is not a comment. It's called an Attribute, is built into PHP itself, and while it does use a comment-syntax, it's the old style that is largely unused today ("#" at the start of a line). https://www.php.net/manual/en/language.attributes.overview.p...
JSDoc isn't similar at all, unless you build a compiler that does different things based on your JSDocs.
> Reading about JSDoc gives me the same uneasy feeling, even if it’s not quite the same thing
The key difference with TypeScript is that even "real" TypeScript types never ever affect runtime behavior, they are purely descriptive. This is an explicit goal of the project (and they've had to make some compromises in other areas to uphold it), so I don't see it ever changing
I don't know the details of their situation, but I definitely can relate to the build step being a huge pain in the butt for Node projects. It's why I've stopped using Node whenever I can afford to, in favor of Deno (or maybe one day Bun). I used Deno to build a compiler for a personal language project recently, and it was an absolute delight not having to deal with any of Node's BS. Assuming they can't afford to migrate runtimes at this stage, I definitely get why they'd explore other options
I’d be thrilled to make the concession to a TypeScript flavor of header/implementation file pairs and skip a build step for huge portions of my work. But I spent way too long trying to figure out how to do it and my only remaining hope that it’s even possible is to wait for the “you don’t know?!” replies. (If it’s not clear here, they’d be very very welcome!)
Before:
import { Node } from 'acorn';
import * as code_red from 'code-red';
export const parse = (source: string): Node =>
code_red.parse(source, {
sourceType: 'module',
ecmaVersion: 13,
locations: true
});
After: import * as code_red from 'code-red';
/**
* @param {string} source
* @returns {any}
*/
export const parse = (source) =>
code_red.parse(source, {
sourceType: 'module',
ecmaVersion: 13,
locations: true
});
But I'm not a Svelte maintainer or user, so if this is their choice, I guess it is what it is. It's not something I'd ever consider. There are other approaches for making linked npm package workflows more manageable. There's the one mentioned by one of the VSCode maintainer, but the simplest setup is to just have a watch process running that recompiles on the fly.EDIT: It'd be a great outcome in the end if this conversion spurs DX improvements in Node/TS.
I spend months trying to solicit feedback on new experimental stremaing/cancellation APIs in Node and it's silence for a year until people start using it.
We say that contributors agreed to list pronouns in the readme or we mention inclusivity and oh-boy do a lot of random people from the internet cares about how the volunteers that write the software they use for free refer to each other internally.
Oh boy. If they don't like it, then they don't have to contribute. (Spoiler: none of them are contributing anything.)
> Of course, Svelte developers (not compiler developers) will still be provided type definition files as now, so there will be no change for Svelte developers in terms of typing.
Someone who maintains the JS debugger for VS Code added this (in response to a Svelte developers saying they couldn't use a faster compiler due to debugging difficulty):
> It's an aside from the main PR, but I'm not entirely sure what you mean here. This should not exclude the ability to use alternative TS compilers--in fact, the js debugger itself is built with esbuild. The debugger should also handle runtime transpilers (like tsx) just fine.
Edit, btw: Most complex types in the MR are now completly broken. It's crazy that there is a serious project out there who tries to mix jsdoc and typescript interfaces in the same project. it's like getting bad things from two worlds.
Flow for JS from Facebook also supports types-as-comments, https://flow.org/en/docs/types/comments/ , but those are rather ugly as one has to intermix them with JS rather than using separated comment block on top.
A lot of the new frontend codebases involve a build step before running. For such codebases, TypeScript's build hurdle has already been overcome.
Documentation, with JSDoc back to good old comment/type documentation.
Can't wait to see what clock we set the time back at next.
It makes you think why can't the TS compiler produce JS code with JSDoc annotations instead of source maps. Ship the node packages with that so that debugging into the framework is seamless and easy to edit.
Is anyone using Svelte in production without SvelteKit?
Hows Svelte documentation as of late?
They've been focusing on SvelteKit, so plain Svelte has stayed pretty much the same for a while. It's nice, stable, feels finished. I'm ever so slightly afraid of what could happen now attention appears to be on it again.
The docs + tutorial are very good, even approaching "fun" (YMMV).