Hacker News new | past | comments | ask | show | jobs | submit login

Lordy, I did not expect an internal refactoring PR to end up #1 on Hacker News. Let me provide some context, since a lot of people make a lot of assumptions whenever this stuff comes up!

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 was skeptical at first when we made the change in SvelteKit. However, SvelteKit has a large integration test suite and being able to change the code and rerun the tests against the real final version of the code without waiting for any build step to complete has been a big improvement to productivity and I'm now a big fan of having made the change there. The tradeoff may be a bit different in Svelte core where we have more unit tests and fewer integration tests, so we're still investigating and considering the change, but we do have experience with both approaches and at the end of the day great software can be built using either approach.


I don't use Svelte, but I appreciate the principled approach and the clear explanation.

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.


What if TypeScript could compile to JS/JSDoc instead of source maps? I'm also not a fan of 'go to definition' bringing me to a dead end d.ts file, but also there has to be a better solution than verbosely JSDoc'ing all the things.


There was talk about introducing type syntax as valid but ignored in the JS language, making TS valid JS.

It would take forever to become mainstream but if node and major browsers started to support this tomorrow, along with ESM modules we could drop TS compilation and bundling entirely during development, safely publish npm packages as TS (even a bundled TS) and simplify tooling for monorepos, IDEs, etc.

Unfortunately that wouldn't solve dealing with templates like JSX/TSX or future language syntax/features.

https://devblogs.microsoft.com/typescript/a-proposal-for-typ...


Right yea that solution would be many years out and doesn't work for JSX. As opposed to compiling to JS/JSDoc which could be done today and should solve our problems with stepping into NPM package code without dead ends.


I think this outlines a bigger problem.

JavaScript Ecosystem itself.

It's incredible we do transpiration, minification, bundling to the same language the interpreter is going to read.


> Lordy, I did not expect an internal refactoring PR to end up #1 on Hacker News. Let me provide some context, since a lot of people make a lot of assumptions whenever this stuff comes up!

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.


> It's also a really contrarian viewpoint about typescript which is really popular.

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.


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

To be fair, "We are so invested in TypeScript we're dropping it!" is an equally astonishing take. It's language I'd expect from Google about any of their projects.


But that's the thing, it's _not astonishing_. It _would_ be astonishing if we were abandoning typing Svelte. We're not. We're not even abandoning TypeScript -- the whole project will still run `tsc` and enforce complete type-safety, it just won't use the compiled output. This is _abandoning one syntax for another_ because one syntax doesn't require a build step and a huge toolchain to run and debug.


> JSDoc _is_ TypeScript

This is surprisingly true in a way. TypeScript is not a language(1), it's primarily a linter-assisting overlay atop of an actual language, JavaScript. Also, there's a linter that outputs and bundles JS, shedding the alien type annotations and also injecting its own, very partial runtime.

So, JSDoc is just a linter/documenter aid. And so is TypeScript.

(1) TS is not a language: it has no spec, no reference documentation. It defines no behaviors, in particular, no runtime behaviors. It sits atop of various JS versions, layering over them in unspecified ways. TS is a linting layer, and also is a hack.


> JSDoc _is_ TypeScript

No. At least, it didn't used to be. JSDoc had its own syntax, but now you can piggyback its format and put TypeScript inside. So now you can write `@type {Record<string, number>}` instead of the "classic" `@type {Object.<string, number>}`, and use some more TypeScript goodies.

You can even kind of use generics with JSDoc, still thanks to TypeScript, but then again... you're not really leaving TypeScript, you'll still have to deal with TS versions, and probably with some of the not-clearly-explained "papercuts" from above.

And finally, I'm not sure that JSDoc+TypeScript is perfectly equivalent to TypeScript. I have a hunch that some of the advanced strategies, e.g. involving `infer` or `extends`, aren't really replicable in JSDoc - or at least I have no clue how to do that in JSDoc - so we'll have to settle for weaker definitions in some cases. So, I'll have to see if it's actually "the same outcome".

I admit I'm no JSDoc guru, so maybe if somebody is compelled to try harder they might actually find a solution for a transition from TypeScript to a completely equivalent alternative. I'm all ears... but surely, if you try too hard the point will be lost.

All of this just to help the Svelte community to contribute - I'll have to take Rich' word for it. For now, it's the only community I've heard that switched from TypeScript in favor of JSDoc. They'll have to deal with a more verbose and less readable codebase for sure, I think there's no doubt about it. Is it really helping the contributors?

It may work for an open source project with a strong governance, maybe. I have a very different experience with projects that decided to use JS instead of TS. Unless we're talking about a very small project, it always turned out to be an ungodly mess.

> it doesn't have to be built to run

If this is a problem, then you have other problems...


Late to this party, wanted to add something here. Wholly agree with your perspective.

The counter-trend to this is the structural-first approach to TS, which eschews return types, and uses mechanisms like the 'satisfies' keyword to ensure that the type evaluates against known symbols, while maintaining the language-server inferred type product in all contexts. The tl;dr goal of this method is to make code that presses compiler-safety at every edge.†

Inversely, the JSDoc method sees you explicitly define everything, and what you save is writing a d.ts file (sometimes). You can pass the TS compiler over it, but it's not going to give you the incremental typing benefit. What you get are a bunch of black boxes with a published contract and a pretend-really-hard approach to typing.

That is frequently fine in cases like libraries. What I worry about is your average dev†† assuming this objectively traction-control-off approach to writing JavaScript approach is good, or rigorous. I don't doubt the svelte team is perfectly capable of writing code in this mode of delivery, and has an armada of tests to back up the proposition. The average dev always opts for easy, and therefore will take to this approach with gusto, but balk at the testing that is necessary to make up for some of the blackbox behavior (blind calls, function internal any, implicit unknown passing that TS would reject, et al) that may not be fully consistent with the behavior the purported type signatures suggest.

†for the sake of argument, I'll define "average dev" as people with a few years of experience still feeling out their place in the industry, and the 9-5 contingent who may or may not own a computer at home and like that paycheck.

††I don't necessarily rep this approach, it's just the other extreme*


JSDoc TS is well documented: https://www.typescriptlang.org/docs/handbook/jsdoc-supported...

It's not 1:1 in features though, but because you can import definitions https://www.typescriptlang.org/docs/handbook/jsdoc-supported... you can use a file a part whenever you encounter any of those advanced features / edge cases current JSDoc does not support.

Like other said, it's still TS after all, and there are escape hatches when needed.

In so many projects I use JSDoc TS, the amount of projects that ended up needing a manual .d.ts file not utomatically generated via `tsc` can be counted in half hand.

Maybe people could give it a try, after all if you comment a method, beside its signature and return types, you can as well just move types in there ;-)


That's an interesting hybrid approach, thanks Andrea.

Is this what Svelte will use? (Asking anybody that knows, of course.)

Anyway, to me the main problem in using TS with libraries is that we have 3-4 major releases per year, and they're just too many. Unless one takes a very restrained approach, releasing very generic (and thus less helpful) types that won't (presumably) break future (or past) versions of TypeScript, we need to release with `typesVersions` targetting n different versions of TypeScript. That's an ever-growing bother indeed for maintainers as time passes.

And I fear the hybrid approach above won't escape this issue. So using "pure" JSDoc or JSDoc with just a sprinkle of TypeScript actually makes sense... But I'd expect this workflow to be winning with smaller projects, and that's why this announcement for Svelte has been surprising to me.


> tbh, this seems pretty far out there. Sourcemap file size is a non-issue, they're not gigabytes

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.


> it starts to add up both in bandwidth, and in storage taken

Are we really talking about disk space in 2023? Seriously?

And bandwidth? Like we don't have several cache systems - including npm's - that can help?

> how to make your software easier to change in the future

Ok, is there someone who can explain in details how would that help?


> Are we really talking about disk space in 2023? Seriously?

Well, it adds up, if you're doing multiple projects.

Doing a quick scan of my work desktop, I find 43,237 filenames matching ".js.map". The biggest is at ~10,000 KB, the smallest at 1KB. If we assume the average is just 200KB, in total they represent ~8.6 gigabytes (200 kilobytes 43237). That's not nothing.

> And bandwidth? Like we don't have several cache systems - including npm's - that can help?

Being conservative with bandwidth is a good thing for most. Not only will everything download faster because less is needed, but it'll probably be cheaper for you to run your application as serving less bandwidth either gives you a small bill if you use cloud, or requires less hardware if you're going the dedicated route.

Not to mention not everyone sits with the latest maxxed out Apple hardware for working, especially outside the SV bubble. These people deserve to be able to have a good development environment as well.

Overall, everything gets faster and cheaper if you save bandwidth.

> Ok, is there someone who can explain in details how would that help?

It's easy, the lesser moving parts your application has in the abstraction ladder, the safer and easier it gets to change things in the future.

Transpiling from one language to another to get a benefit you can also get by not transpiling a language from one to another, seems like a no-brainer to me in most cases.


Just jumping in here to applaud the usage of "luddite numpties" in a sentence.


When I try to google this, the top (and only relevant) result is this hn post… mind throwing a bone?


Search for the definition of the two words individually and you'll be good!


Great move, Rich! It's quite enjoyable working without sourcemaps.

I'll add that IntelliJ+Copilot makes writing solid JSDoc very fast and easy.


Good on you for making this clear


I've been doing exactly the same thing for a number of years, and I find it a much more intuitive way to use TypeScript.

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!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: