What is the proportion of JS libraries in the wild which provide TS type declaration files, either via DefinitelyTyped or provided by the lib itself? Is it normal to have to write your own declarations, or do most libs provide them these days?
Its actually quite rare to see a library without either first or third party support these days. Many new libraries are either written in typescript, or the authors have taken care to create declaration files or contribute to definately-typed. If a library reaches any degree of popularity it usually isn't long before a third party declaration appears.
Older libraries that are long abandoned by their maintainers usually don't have anything. At work we pretty much ignore all libraries that don't have types from somewhere these days, but that doesn't eliminate many things.
I agree on ignoring libraries without definitions.
Having to write the definitions myself usually isn't a huge pain, but it's a big red flag showing that it's probably abandoned, and there's no community support around it anymore (or possibly ever).
In those cases I will sometimes try to post an offer to write their definitions (or the build step to generate definitions from slightly modified existing JSDoc comments in even more rare cases) and PR them to the project if they like. How a project responds (or doesn't) to that Issue often tells you so much about current maintenance habits.
Almost all of them provide them, although sometimes they are slightly out of date. I think I've had to write my own declaration files (or type a library as any) for one or two libraries in years
Whilst TS does technically contain breaks, these are normally simple increases in the power of the type-checking. It's finding more errors in code that previous seemed fine. Think of it like adding more ESlint rules.
It's rare for there to be a breaking change in the JS emit.
The TypeScript team work hard to preserve compatibility. Breaking changes are explicitly managed and communicated ahead of time. There is a concept of a breakage-budget per-release. This means if you stay up to date, the cost of each upgrade should not be huge. Orta and Nathan on the TypeScript team talk about this in this podcast episode: https://dev.to/devteam/devnews-s1e4-typescript-4-0-gitee-chr...
The majority of breaks are due to the checker getting better. So code that passed now errors. Most of the time pre-existing published DTS files still operate fine.
Yeah, in most cases the breaks are because of how DTS files are interpreted in consuming projects, as new strictness checks light up. Most of the time that has seemed to be what the DTS files really intended and the previous interpretation less useful.
A useful example is Strict Null Checks which started to treat unadorned types as non-nullable (string versus string? versus string | null). In most cases the runtime behavior of libraries were already throwing errors when nulls were passed in, and the extra checks helped immensely. In rarer cases "oh yeah, null is totally a valid thing to send to this API and it has some defined behavior that we document/should document" and the DTS files were encouraged to annotate their types to include that. In the worst where libraries had such APIs but failed to update their DTS files, there were explicit casting workarounds in consuming projects (the awkward `null as string` and the so called "damn it" operator `possiblyNullString!`).
The breaking changes don't change runtime behaviour, just the type checking. Its more like the the linter is getting stricter over time. Your test will still pass at runtime, but they might start failing at compile time.
Also, for the cost of dealing with a breaking linter once and a while it helps enormously with upgrading javascript libraries provided they have up to date type definitions. If an API changes you are immediately alerted to many of the places where your previous assumption are now wrong.
It also completely changes the way you write code. Often time you can just go to the leaves of your application, make the change you want, and then just follow the compiler errors all the way back up to the top. When it compiles there is decent chance that it will run successfully first time.