htmx
htmx copied to clipboard
Convert htmx to TypeScript 😍
TypeScript would bring lots of DX benefits to the htmx source code. Besides the obvious strict type checking, we would be able to write code using the latest and greatest ECMAScript 2021, but continue compiling to ES5 (to support IE11), or any version of ECMAScript really, with a single config setting.
{
"compilerOptions": {
"target": "ES5"
}
}
I've started a WIP branch in which I've converted htmx.js to htmx.ts, changing the minimum amount of code possible, and it is compiling with all tests passing.
@1cg in theory, we could merge this branch into the dev branch before the next minor release, and start converting the source code incrementally.
Of course up to @1cg to decide if this switch is actually worthwhile, but will have to say no thanks because:
- Increased barrier for contributions.
- More complex, slower build process.
- Type checking may not even be of tangible benefit for htmx (htmx has a nice test suite).
The ECMAScript spec will probably supersede TypeScript in the near future anyway. This has happened historically with other dead Javascript dialects (example: when classes were included in ES6).
EDIT- People should be aware OP has been promoting this issue to twitter followers... we may get feedback from drive-by typescript users.
While you may have some good points, I still think that the benefits of moving to a modern codebase (rather than one that resembles 2014, no offence @1cg!) far outweigh the arguments given, especially for the core contributors of htmx.
Increased barrier for contributions.
That's debatable, as TypeScript is a superset of JavaScript and helps to catch errors early.
More complex, slower build process.
The build process remains the same: npm run dist
Type checking may not even be of tangible benefit for htmx (htmx has a nice test suite).
Type checking helps to write more robust code and leads to tighter integration with code editors that can then catch errors much more reliably. This doesn't question the value of the test suite at all, which validates the functionality of the code rather than the data flow.
In general, I think any library should be written in TypeScript... and probably everything else, too, for the reasons cited above.
The ECMAScript spec will probably supersede TypeScript in the near future anyway. This has happened historically with other dead Javascript dialects (example: when classes were included in ES6).
There's just so much momentum behind TypeScript (and Microsoft as well) that I don't see TypeScript going anywhere any time soon. So I don't think we're looking at CoffeeScript all over again.
Remember, TypeScript just adds types to JavaScript. Strip the types, and you have fully up to spec JavaScript code.
If anything, I could see TypeScript being subsumed into JavaScript at some point... which means your code would likely still work
But let's take the worst-case, which is that in 4-5 years (given how slowly these standards get implemented, I think this is likely reasonable), ECMAscript has some kind of incompatible type system built into it. You'll still have benefitted for 4-5 years from all the things TypeScript gives you, and your code will still compile down to JavaScript regardless of any standards change.
And it's very likely even if/when types do come to the ECMAscript standard that you'll be transpiling for years after that anyway, for backward compatibility reasons.
More complex, slower build process
tsup is what I'd recommend for builds -- it's actually quite fast and simple:
https://github.com/egoist/tsup
I've used it before in some plugins I've written, and the implementation is easy:
https://github.com/nystudio107/rollup-plugin-critical/blob/master/package.json#L30
Here's my WIP fork: https://github.com/bencroker/htmx/tree/typescript
I think this may have already been settled, but I'll just add this for posterity. Typescript is made for codebases EXACTLY like htmx. The compiler can be set to work with existing *.js files, and there's even an option to include (almost) all of the Typescript annotations as backwards-compatible JSDoc comments.
A small band of Typescript fanatics (including me) have been sneaking JSDoc/Typescript comments into htmx and hyperscript for a while, now :) This gives us the benefits of using Typescript with little additional developer overhead. The comments are a little more clunky than pure Typescript, but it lets us get started while we work out the infrastructure.
Here's my type definitions: https://github.com/leevigraham/typescript-htmx-types
@leevigraham should submit them to Definitely Typed -> https://github.com/DefinitelyTyped/DefinitelyTyped
Nice work! Even as a WIP it's useful!
@khalwat That was the plan I think but I was just learning typescript so I wasn't sure it was up to snuff. Then I got the very strong impression that there was no future for TS in HTMX so I kinda lost interest.
More than happy for anyone to fork my repo / take over.
The ECMAScript spec will probably supersede TypeScript in the near future anyway. This has happened historically with other dead Javascript dialects (example: when classes were included in ES6).
https://www.youtube.com/watch?v=O9F4K804XC8
History repeats itself.
RIP Typescript soon.
Also re-removing the build step = Finally :+1: @1cg
Firstly, I'm thrilled if typing becomes part of the actual ECMAScript spec. That's an ideal world scenario for me.
Arguably, if things like TypeScript didn't exist, the official spec would not be pushed forward. I think it's great that various JS technologies are rolled out, and the ones that get proven "in the field" are rolled into the spec.
This cycle will continue into the future; there will likely always be a build step to allow for the use of modern versions of the language, whilst still offering backward compatibility.
It takes a long time for the ecosystem to catch up. The spec has to be drawn up, approved, and then browser vendors slowly roll it out with varying degrees of support.
So the idea of "no build step" probably will never happen, if you want to be using technologies as they evolve.
I would like to add a +1 for converting to Typescript, or at least adding a definitions file.
@adrienne there's one at https://github.com/bigskysoftware/htmx/blob/master/src/htmx.d.ts
@bencroker is there a quick demo anywhere of importing/making HTMX work nicely? (I'm still learning TS and I'd like to use this in a project where the existing JS, which i didn't write, is all in TS)
I'm not sure, the Discord server would be the place to ask.
@bencroker Guess I can archive my repo then.
@leevigraham I haven't compared them, feel free to PR any missing definitions to this repo.
Type checking may not even be of tangible benefit for htmx (htmx has a nice test suite).
Here is a recent example of a bug that would have been caught be a type checker and wasn't caught by the existing test suite: https://github.com/bigskysoftware/htmx/pull/1156
A nice test suite doesn't mean you wouldn't benefit from types. On the contrary, types are a form of tests and running a type checker is like running a test suite. When applied well, types can supersede a whole class of tests like "Am I forwarding the arguments in the right order".
You're preaching to the choir here, @thomaseizinger, but this is a great example to strengthen the argument for TypeScript.
Yeah, I'm a big fan of Typescript, too. But it's unlikely that htmx will get translated fully into TS.
Fortunately, we have made the compromise of using Typescript/JSDoc comments, which are a little more bulky but still 100% Javascript compatible (see my note above)
Since I can still use the TS compiler to statically analyze the htmx source code, I've found that using JSDoc comments gets me about 95% of the benefits of using Typescript without having a separate compile step.
Does this "comments only" approach work for you, @thomaseizinger? We've made some progress in the past towards adding accurate JSDoc annotations and a Typescript .d.ts header file. Do you have any interest in making improvements there?
JSDoc is documentation oriented, while Typescript adds static typing to Javascript. These tools do have some parts in common, they allow for type checks, for example, but their purpose is different.
Also, remember that if you strip the types from Typescript, you end up with valid Javascript, that's baked into the spec of the language. So I'd call it a build step, not a compile step.
While adding documentation is always good, you can have both: Typescript and also TSDoc, they aren't mutually exclusive. For any library, I think Typescript is a really good choice.
You'll be surprised at how many bugs you find and fix in the process of refactoring it to Typescript, and you can do it incrementally, slowly making it more and more strict as you refactor.
@khalwat - Yes. I'm very familiar with Typescript, and I'd love to use Typescript in htmx, but that's not an option.
However, the Typescript compiler CAN parse JS files directly, and Typescript uses JSDoc comments directly. It's not a separate toolchain; it's another way into the Typescript ecosystem.
As I said above, JSDoc comments are not perfect -- they takes up more space and can be a little clumsy in places -- but using this style allows us to have 95% of the benefits of Typescript WITHOUT introducing a separate compile dependency, which is the main requirement that prevents us from using Typescript outright.
It's great to have more fellow Typescript zealots in the htmx community. If you're interested, check out what we've got so far and in the way of *.d.ts headers and JSDoc comments. Pull requests that shore up internal consistency and reliability will be a no-brainer to merge :)
@benpate Yeah those comments were also intended for anyone else reading, just to clarify things.
Maybe I'm missing why htmx can't be refactored to Typescript? The main issue seems to be the build step? Can you help me understand why this is a blocker?
If htmx is published as an npm package, you can add a prepublishOnly script that does the build transparently before new versions are published, and files to designate only the dist/ (or whatever) files should be published via npm, which should make everything pretty seamless.
Related: https://snyk.io/blog/best-practices-create-modern-npm-package/
If that is the preferred workflow, I think it would make sense to run that as part of CI to make sure it doesn't get outdated!
What is the reasoning that a separate compile dependency is a big problem? There is already minification and testing as part of the build/publish workflow so it doesn't sound like a heavy addition?
I very much enjoy that as a user of HTMX, I don't need a build pipeline at all but if one exists here already, extending doesn't seem that bad? Perhaps I am missing something!
What is the reasoning that a separate compile dependency is a big problem? There is already minification and testing as part of the build/publish workflow so it doesn't sound like a heavy addition?
I very much enjoy that as a user of HTMX, I don't need a build pipeline at all but if one exists here already, extending doesn't seem that bad? Perhaps I am missing something!
Currently there's a dist script that looks like this:
"dist": "cp -r src/* dist/ && npm run-script uglify && gzip -9 -k -f dist/htmx.min.js > dist/htmx.min.js.gz && exit",
Ironically, it actually could be simplified when converted to Typescript using tsup to something like this:
"build": "tsup src/index.ts --minify --sourcemap --dts --format cjs,esm",
...and then to make things easier, just add a prepublishOnly script that automatically runs build whenever a new version is published.
As you said, there's already a build step, I don't see that as being an issue.
i like being able to debug the unmodified version of javascript locally when I develop, rather than having to have a build step or source maps or whatever.
JSDoc has been a half-way house giving us some type checking (I'm an old java developer, I am not opposed to types) which I like.
Do browsers support typescript directly yet?
No browsers I'm aware of support Typescript directly. If they ever do, that's fine -- but you can reap the DX benefits now.
I think you'd be surprised by the DX benefits you get from something like Typescript in combination with Vite for HMR when developing.
You get the static type checking benefits from Typescript, with hot module replacement of the code while developing, so never having to hit the refresh button in your browser while developing.
Incidentally, you can use Deno if you want a Node-like environment that natively supports Typescript.
Another benefit would be that you can make use of the module system and split up the current monolith into independent modules.
yep... and tree shaking will remove unused code... just lots of benefits to using a modern dev system imo
htmx has excellent long term staying power because of it's simplicity, zero dependencies, ultra-low friction to contribute or debug.
This has always been a killer feature of htmx
It's why we're here and not just using React / Svelte / etc. htmx is a uniquely magestic monolith in this space with a lot of passionate contributors.
On the other hand, I realise it's tempting and easy to add extra dependencies and build steps using an "in vogue" build system of the month, but this stuff can be difficult or impossible to remove in the future, and will put htmx on a dependency death clock at worst- Like most other libraries in this space.
i like being able to debug the unmodified version of javascript locally when I develop, rather than having to have a build step or source maps or whatever.
It's a highly refreshing experience.