TypeScript is terrible for library developers

This page summarizes the projects mentioned and recommended in the original post on news.ycombinator.com

Our great sponsors
  • SurveyJS - Open-Source JSON Form Builder to Create Dynamic Forms Right in Your App
  • InfluxDB - Power Real-Time Data Analytics at Scale
  • WorkOS - The modern identity platform for B2B SaaS
  • redux-toolkit

    The official, opinionated, batteries-included toolset for efficient Redux development

  • Heh, it's amusing to see Redux Toolkit referenced here. I'm one of the two main RTK maintainers. My co-maintainer Lenz Weber is responsible for most of our TS type wizardry.

    Agreed that writing TS types for libs can be a pain. I actually did a talk recently on "Lessons Learned Maintaining TS Libraries" [0], where I talked about some of the techniques we used, and some possible TS changes that would be helpful for us as maintainers.

    As one recent example, TS made a change in a 4.8 pre-alpha that broke RTK's `createSlice` types. Lenz tried to come up with a fix, couldn't, and had to add a workaround to check what TS version is being used and specifically use an altered type. Since there _isn't_ a good way to know what TS version is being used, Lenz resorted to hacking together a new package that abuses the `typesVersions` property to define a different TS type for _every_ TS major+minor version combo, and then used that to decide what the RTK type should look like conditionally [1].

    Another pain point is debugging type transformations. I reworked the Reselect types in 4.1.x to do a much better job of inferring the argument types for the final selector, based on the intersection of all the input selector arguments. This ended up as a monstrous type that does a types-level map + transpose + intersection [2]. It took me weeks to get this working right, and I frequently had to break it down into multiple small intermediate types to see how TS was processing each step.

    I know that someone on Twitter was recently working on an alternate TS type-checker based on bytecode, and they said they had some kind of a working types-level debugger [3]. Having something like that officially, where I could see each step of how TS was transforming the types, would be _hugely_ valuable.

    There's a couple folks like AndaristRake who are able to dig into the internals of the TS compiler itself to trace how it's interpreting the types. I definitely don't have that ability :)

    [0] https://blog.isquaredsoftware.com/2022/05/presentations-ts-l...

    [1] https://github.com/reduxjs/redux-toolkit/pull/2547

    [2] https://github.com/reduxjs/reselect/blob/v4.1.5/src/types.ts...

    [3] https://twitter.com/MarcJSchmidt/status/1539787500788613120

  • reselect

    Selector library for Redux

  • Heh, it's amusing to see Redux Toolkit referenced here. I'm one of the two main RTK maintainers. My co-maintainer Lenz Weber is responsible for most of our TS type wizardry.

    Agreed that writing TS types for libs can be a pain. I actually did a talk recently on "Lessons Learned Maintaining TS Libraries" [0], where I talked about some of the techniques we used, and some possible TS changes that would be helpful for us as maintainers.

    As one recent example, TS made a change in a 4.8 pre-alpha that broke RTK's `createSlice` types. Lenz tried to come up with a fix, couldn't, and had to add a workaround to check what TS version is being used and specifically use an altered type. Since there _isn't_ a good way to know what TS version is being used, Lenz resorted to hacking together a new package that abuses the `typesVersions` property to define a different TS type for _every_ TS major+minor version combo, and then used that to decide what the RTK type should look like conditionally [1].

    Another pain point is debugging type transformations. I reworked the Reselect types in 4.1.x to do a much better job of inferring the argument types for the final selector, based on the intersection of all the input selector arguments. This ended up as a monstrous type that does a types-level map + transpose + intersection [2]. It took me weeks to get this working right, and I frequently had to break it down into multiple small intermediate types to see how TS was processing each step.

    I know that someone on Twitter was recently working on an alternate TS type-checker based on bytecode, and they said they had some kind of a working types-level debugger [3]. Having something like that officially, where I could see each step of how TS was transforming the types, would be _hugely_ valuable.

    There's a couple folks like AndaristRake who are able to dig into the internals of the TS compiler itself to trace how it's interpreting the types. I definitely don't have that ability :)

    [0] https://blog.isquaredsoftware.com/2022/05/presentations-ts-l...

    [1] https://github.com/reduxjs/redux-toolkit/pull/2547

    [2] https://github.com/reduxjs/reselect/blob/v4.1.5/src/types.ts...

    [3] https://twitter.com/MarcJSchmidt/status/1539787500788613120

  • SurveyJS

    Open-Source JSON Form Builder to Create Dynamic Forms Right in Your App. With SurveyJS form UI libraries, you can build and style forms in a fully-integrated drag & drop form builder, render them in your JS app, and store form submission data in any backend, inc. PHP, ASP.NET Core, and Node.js.

    SurveyJS logo
  • node-app-store-connect-api

    A library to support Apple's App Store Connect API

  • Here's a perfect example. I maintain a simple Node library designed to connect to Apple's App Store Connect API. https://github.com/dfabulich/node-app-store-connect-api

    It accepts, as a parameter, an URL for Apple's REST API. My library handles authentication, and returns the parsed JSON result, with a handful of tweaks to make the API more usable in JavaScript.

    Depending on which URL you request, you'll get different result object back. You could get a single object in response, or an array of objects, and the type of returned objects is different for each URL type.

    How would you add TypeScript types to this API? Well, Apple provides an OpenAPI documentation of all of their URLs, which I could use to autogenerate types, but then, how would I handle all of those types in response to the user's string input?

    Well, it turns out that TypeScript is so amazingly fancy that you can write very clever code to parse strings at compile time, extracting parameter types etc. from string literal types. https://lihautan.com/extract-parameters-type-from-string-lit...

    The documentation explains how an API like this:

       app.get('/purchase/[shopid]/[itemid]/args/[...args]')

  • Scrawl-canvas

    Responsive, interactive and more accessible HTML5 canvas elements. Scrawl-canvas is a JavaScript library designed to make using the HTML5 canvas element easier, and more fun

  • My personal experience as a library developer, who has written my library in JS, not TS ...

    TS is an excellent choice for a lib dev starting a new project today. I can see the advantages of using TS for the library code - in particular for a library that gets popular and welcomes contributions from other developers. However TS is a nightmare for someone like me who: 1. started writing the library 9 years ago; 2. has let the library get "quite" big; and 3. has only learned to use TS in the past year (for the day job) and is nowhere near to becoming a types expert.

    I've had experience of people suggesting I rewrite the library in TS. Sometimes those suggestions have been quite 'evangelical' in their tone. As an (essentially) solo developer I just don't have the time, capacity or willingness to do that work - however much the end results might please others.

    I also understand that having type definitions file for the library's interface is, nowadays, a critical factor if the lib dev wants others to use the library in their projects. But writing a .d.ts file for a large, mature repo to at least help those potential users can quickly turn into a World of Hurt. I know this because I've done that work[1] and I never want to do it again.

    As much as I know that TS is a Force for Good in the JS coding world, there are days when I detest it!

    [1] - link to the Scrawl-canvas .d.ts file on GitHub - https://github.com/KaliedaRik/Scrawl-canvas/blob/master/sour...

  • tsdx

    Zero-config CLI for TypeScript package development

  • I don't depend on the actual typescript docs much but thankfully in @types and in tons of repos there are examples of well written typescript code.

    The amount of JS and TS out there is also a bit of a foot gun though so stick with heavily used/starred libs if you aren't sure.

    One tool that helps a lot with developing libraries in typescript is TSDX[0] or its successor dts-cli[1] and there is a bunch of good stuff in awesesome-typescript[2].

    Maybe library devving is harder?(more work?) with tyepscript but it is worth it for the end developer, especially if that end developer is you. If you aren't using your own libs then you're probably getting paid by someone else to make them or... idk.

    https://github.com/jaredpalmer/tsdx

  • dts-cli

    Zero-config CLI for TypeScript package development

  • awesome-typescript

    A collection of awesome TypeScript resources for client-side and server-side development. Write your awesome JavaScript in TypeScript

  • InfluxDB

    Power Real-Time Data Analytics at Scale. Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.

    InfluxDB logo
  • TypeScript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • > Being able to write complex types in a syntax that more closely resembles JavaScript

    Yikes. This is how you end up in preprocessor hell. Macros are generally not a good thing. (Fyi: TS types are already Turing-complete which is arguably a mistake.)

    > Being able to debug types, not console output

    Eh. It's not like Java has a "type debugger." Why is this needed? Why are your types so complex? Weird ask.

    > More comprehensive documentation on writing advanced types

    Really beating the same drum here.

    > A typescript specification

    What does this mean? We have a pretty clear typescript spec[1].

    [1] https://github.com/microsoft/TypeScript/blob/main/doc/spec-A...

  • GoJS, a JavaScript Library for HTML Diagrams

    JavaScript diagramming library for interactive flowcharts, org charts, design tools, planning tools, visual languages.

  • I am really surprised by this guy's opinion. I make GoJS (https://gojs.net/), a diagramming library written in TypeScript. The project began in 2011 and we converted it to TS in 2018. It's been a huge plus. The sole downside was the initial time it took during conversion, but even in doing so we caught bugs with incorrect input types, documentation mistakes, etc.

    On our end, it enforces type safety better than the Google Closure Compiler. There has scarcely been a problem with type complexity that was not ultimately our fault. Just a couple minor things that TS amended later. For that matter the TS experience has only gotten better, generally.

    On our users end, we can now give them a .d.ts file that's much richer and easier for us to produce to aid their autocompletion. And we can use that .d.ts file to ensure that all the methods we intended to expose/minify are getting exposed. The advantages with the .d.ts and documentation make it feel almost essential to me for library developers to consider TS.

    TypeScript has only made debugging easier, much easier since it catches errors at time of typing unlike the closure compiler. The sole exception is that debugging is a bit slower since I have to transpile instead of just refreshing the browser. But I have tsc set to compile a relatively unminified version of the JS. But if the slowness gets to me, I can just edit the JS output until I solve the issue, and then carry those edits over to the TS. This has never felt like a problem, though maybe his library is significantly more complicated.

    Feel free to ask me anything if you have questions about library design + TS.

  • TanStack Query

    🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.

  • Perhaps the React-Query source itself is a good example of when "simple" is still not "easy to read/write":

    I picked out this file pretty arbitrarily: https://github.com/TanStack/query/blob/main/packages/react-q...

    The author of react-query seems to be very clear at communicating how the library works and the library itself provides a great developer experience, but it's also an example of how much work can go into correct typing in library code.

  • pandas-stubs

    Public type stubs for pandas

  • It gets a lot more complicated than that. One of many, many examples: https://github.com/pandas-dev/pandas-stubs/blob/v1.4.3.22082...

  • docs.rs

    crates.io documentation generator

  • Rust has https://docs.rs

    Golang entire standard library is documented. Plus with how the language is designed docs don’t need to change with new versions. Just with new functions.

  • flow-typed

    A central repository for Flow library definitions

  • I'm very curious, which "Redux code" are you referring to here?

    I don't think the `redux` core lib ever shipped any Flow types itself. Looking at the FlowTyped repo, I see community typedefs at https://github.com/flow-typed/flow-typed/tree/master/definit... , and the Git history suggests those were indeed written by community members.

    (of course on the flip side, _I_ didn't even start learning TS myself until 2019, and goodness knows _that_ has been a lot of trial and error over time :) )

NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts