chore: revamp how we export types #2118
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Finally, this is what all of my previous PRs recently have been leading up to. I've spent a lot of time reading up on TypeScript, JSDocs, and reviewing how different projects choose to maintain their types and settled on this for us.
I personally like writing JavaScript, not TypeScript. So I wanted to maximize use of the TypeScript tooling, but without adopting the TypeScript language. We were doing this already by typing through JSDocs, but this takes things further.
The fundamental change that this applies is that instead of manually maintaining type declarations for our public interface, we now generate those declarations using
tsc
. Runningyarn run build:types
is now part of the build process before publishing to npm, similar to how we must runbuild:bundles
to create the CJS and browser bundles too.Benefits
Breaking Changes
I've decided to drop default exports from the library. My original plan was to keep them in SVGO v4, and export with both named and default exports. However, this seems a little more annoying to maintain than I was expecting.
Reasons:
Not the main reason, but other considerations:
This has no impact on users who:
require
).However, if you are using the
import
syntax and imported SVGO via the default export, then you must adapt your code for v4:Changes
@typedef
unless we actually want to declare/export a type to be used in other files. TypeScript generates anexport
whenever we used@typedef
. This is also why for common types likeXastElement
, the IDE would often auto-complete it to the@typedef
of a random file rather than the file that actually defined the type..d.ts
files to JSDocs to maintain the type closer to the documentation.types.d.ts
totypes.ts
. The.d.ts
format is usually to define types for code you don't control, which doesn't apply in our case. When documenting your types, one should use.ts
.types.ts
, as we'll generate types for the rest from the JSDoc types.= undefined
in the JavaScript function signature, and prefer using the=
suffix in the JSDoc type.package.json
, we no longer specifytypesVersions
.exports.types
overtypesVersions
anyway.Testing
.test-d.ts
file. I can expand this later, but it tests the most important thing for now, which was the issue reported inoptimize
types missing from svgo-node.d.ts in 4.0.0-rc.1 #2078.Documentation
@example
in their documentation that featured an arrow to separate before vs. after. I've normalized the indentation of the arrow to 2 spaces just to keep it consistent between examples.Chores
CONTRIBUTING.md
to refer to the new file to update when making a new plugin.CONTRIBUTING.md
to require Node.js v16 as a minimum, and clarify why..gitattributes
..gitignore
and add some comments.Related
optimize
types missing from svgo-node.d.ts in 4.0.0-rc.1 #2078optimize
forsvgo-node
#2099 — Alternate solution.Thanks
I want to give a special thanks to @open-wc who have written great articles on how they handle their type declarations, which I largely referenced to implement the workflow here.
The Open Web Components team have a great article titled Generating TypeScript Definition Files from JavaScript. This was very helpful because most guides share how to generate types declarations, which is the easy part, but don't dive into much detail on workflow or a good way to incorporate the generated types into a package to publish. Meanwhile, open-wc does dive into deal and have many simple examples of the setup in their repositories.