Description
A few years ago we took the decision on TypeScript to not convert modules to the language, because it's not a standard, it's controlled by a single vendor, it requires lots of extra tooling and there were far more JavaScript developers than TypeScript developers, and all TypeScript developers could write JavaScript but the reverse was not always true.
We were going to use JSDoc comments to generate types so people could use libp2p/ipfs modules in typed environments. TypeScript developers would get types, and JavaScript developers would get comments, everyone would be happy.
Fast forward a few years and what's changed? TypeScript has gone from strength to strength, that single-vendor has made some significant plays in open source with acquisitions of npm and GitHub so they're not going anywhere. Far more developers are writing TypeScript than before.
The JSDoc comment thing didn't work out - it's full of gotchas and introduces so much cruft to the codebase that it makes it unpalatable to both JavaScript developers and TypeScript developers - full TypeScript ends up being much less verbose. We tried writing complex types in .d.ts
files but the tooling isn't there to validate them, so we've ended up writing .ts
anyway.
Meanwhile JavaScript has moved on, as it did from callbacks to promises, now it's away from CJS and towards ESM.
We've been shipping most new code in dual CJS/ESM mode which has meant we've been able to support future-tech like skypack but also maintain compatibility with older tools that use the resolve module from browserify like jest, this is also full of footguns, for example instanceof
not working between instantiated from CJS then used with instanceof
in ESM.
Many of our dependencies are now ESM only - since we bundle CJS and ESM we can't update to these as our CJS code would end up pulling in the ESM dependency via a require
which isn't compatible.
Fast forward to now. We're standing on the cusp of a CJS to ESM transition, so why not take the opportunity this presents to embrace the peace of mind TypeScript brings at the same time.
We will refactor existing libp2p modules from CJS to TypeScript which will be published as ESM only with export maps and all that good stuff. This will let us move quickly and safely while supporting new tools and environments.
Porting
A cheat sheet for porting existing modules. This will evolve over time as we move some of these steps into Aegir itself in order to reduce the amount of boilerplate required (testing/coding flow, I'm mostly looking at you).
- Re-use centralised ts config: https://github.com/libp2p/js-libp2p-utils/blob/chore/convert-to-typescript/tsconfig.json
- Build using tsc: https://github.com/libp2p/js-libp2p-utils/blob/f31fa9400a3f96cf3b1e0e112568bc72dba5ae9d/package.json#L49
- All src/tests in ts which means you have to build before running tests: https://github.com/libp2p/js-libp2p-utils/blob/f31fa9400a3f96cf3b1e0e112568bc72dba5ae9d/package.json#L40
- Specify test files under /dist to the test runner: https://github.com/libp2p/js-libp2p-utils/blob/f31fa9400a3f96cf3b1e0e112568bc72dba5ae9d/package.json#L41
- Output type is "module": https://github.com/libp2p/js-libp2p-utils/blob/f31fa9400a3f96cf3b1e0e112568bc72dba5ae9d/package.json#L6
- Public API defined in "exports": https://github.com/libp2p/js-libp2p-utils/blob/f31fa9400a3f96cf3b1e0e112568bc72dba5ae9d/package.json#L7-L26
- Types in "typesVersions": https://github.com/libp2p/js-libp2p-utils/blob/f31fa9400a3f96cf3b1e0e112568bc72dba5ae9d/package.json#L27-L34
PRs
- feat: split out code, convert to typescript js-libp2p-interfaces#111
- feat(!): convert to typescript js-libp2p-utils#20
- feat: convert to typescript js-libp2p-tcp#152
- feat: convert to typescript ipfs-shipyard/varint-decoder#4
- feat(!): convert to typescript alanshaw/it-pipe#6
- feat(!): convert to typescript alanshaw/it-goodbye#5
- feat: convert to typescript alanshaw/it-ws#6
- feat(!): converts to typescript vasco-santos/is-loopback-addr#41
- feat: convert to typescript alanshaw/it-pair#5
- feat: convert to typescript alanshaw/get-iterator#14
- feat: convert to typescript alanshaw/abortable-iterator#16
- feat: convert to typescript alanshaw/it-pushable#12
- feat: convert to typescript alanshaw/it-block#5
- feat: convert to typescript alanshaw/it-reader#7
- feat: convert to typescript alanshaw/it-length-prefixed#18
- feat: convert to typescript jacobheun/it-handshake#4
- feat: convert to typescript (#76) js-libp2p-websockets#140
- feat: convert to typescript js-libp2p-webrtc-star#401
- feat: convert to typescript js-libp2p-mplex#158
- feat: convert to typescript js-libp2p-bootstrap#119
- feat: convert to typescript js-libp2p-mdns#113
- feat: convert to typescript js-libp2p-record#32
- feat: convert to typescript js-libp2p-floodsub#139
- feat: convert to typescript js-libp2p-kad-dht#300
- feat: convert to typescript js-libp2p-delegated-content-routing#67
- feat: convert to typescript js-libp2p-delegated-peer-routing#58
- fix: update interfaces js-libp2p-bootstrap#121
- fix: update interfaces js-libp2p-delegated-content-routing#68
- fix: update interfaces js-libp2p-delegated-peer-routing#59
- fix: update interfaces js-libp2p-floodsub#140
- fix: update interfaces js-libp2p-kad-dht#302
- fix: update interfaces js-libp2p-mdns#116
- fix: update interfaces js-libp2p-mplex#162
- fix: update interfaces js-libp2p-websockets#146
- fix: update interfaces js-libp2p-tcp#172
- feat: update to new libp2p interfaces ChainSafe/js-libp2p-noise#134
- Release v6.0.1 ChainSafe/js-libp2p-noise#137
- feat: convert to typescript interop#58
- feat: convert to typescript js-libp2p-daemon#78
- Add metrics and revamp logic ChainSafe/js-libp2p-gossipsub#206
- feat: convert to typescript #1172
Needed for examples:
Metadata
Metadata
Assignees
Labels
Type
Projects
Status