-
Notifications
You must be signed in to change notification settings - Fork 538
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TypeScript refactor #959
TypeScript refactor #959
Conversation
This pull request is being automatically deployed with Vercel (learn more). 🔍 Inspect: https://vercel.com/primer/primer-components/dv9vvn1wh |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, @colebemis this is looking great! I like the incremental approach, so that we don't have to have a single, massive migration PR and can hopefully fan the work out a bit.
I left a few comments in-line and also have a few questions / suggestions here.
- Is the idea that we will eventually get rid of the
index.d.ts
file and just replace it with a top-levelindex.ts
that exports all of our components / interfaces? If so, maybe we don't need to worry about
❓ Question: How can we programmatically enforce that every component exports a ___Props type?
too much? Because thatindex.ts
would hopefully be a pretty straight-forward
export Box, {BoxProps
from './Box';
and we could probably spot issues fairly quickly?
Another thought is somehow using some sort of doc auto-generation based on the*Props
for the doc site. If these were somehow set up to target the*Props
then it would ensure that they existed and were exported. I know this is kind of hand-wavy as I don't know exactly how to do this, but it was just a thought!
- I wonder if converting all of the tests to TS sooner rather than later would be a beneficial incremental step? Now that we have the infrastructure, it seems like it would be safe and straight-forward, and also might help anticipate any trickier gotchas we might encounter along the way.
Overall this is amazing and I'm super excited to see this work!
export type BoxProps = React.ComponentProps<typeof Box> | ||
export default Box |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth re-considering using default
exports as well? It is probably a breaking change if anyone was consuming directly from @primer/components/lib/Box
or something like that, but if we're going to be making other breaking changes, it might be a fair time to consider it.
I'm not really aware of the main pros/cons of default exports, and it seems like in other code at GitHub we're inconsistent on this already, so maybe it's not even worth looking at 😅
For example, https://github.com/github/details-dialog-element/blob/main/src/index.ts uses a default export, and web components in the dotcom codebase itself seem to be about 50/50.
Just thought I'd mention it to see if it sparks thoughts for others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally I prefer not to use default exports. Here is a good article about it: https://basarat.gitbook.io/typescript/main-1/defaultisbad
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm open to moving away from default exports for our components. A few thoughts:
- If we decide to remove default exports, I'd prefer to do that in a separate PR that updates all the exports of all the components at once. This would allow consumers to update all their imports at once.
- How do we ensure consistency across the codebase? Is there an existing linting rule for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job, @colebemis ! Thanks for responding to all of the feedback!
I'm also on board with making the export default
changes a separate scope of work, even if we possibly wrap it up in a similar major version release?
I think this is good to 🚢 !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approving but lets make sure to resolve the TS errors we were seeing in Memex before merging :)
One question: will changing interfaces to types cause breaking changes in consuming applications? I know sometimes in Memex they import things like SelectMenuProps directly so they can extend them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome - long time coming! Great job!
@emplums and I found that the location of the However, moving the import inside the module declaration causes an error in the Primer React components codebase: @T-Hugs @dmarcey Any ideas about why this might be happening and how to fix it? |
My recommendation is to revert to shipping exclusively the manually-created index.d.ts until the full TypeScript conversion is complete, assuming that will be a relatively fast-follow. |
Based off of @BinaryMuse's original TypeScript PR: #845
Summary
This PR lays the groundwork for an incremental TypeScript refactor of Primer React components.
Impact
From #953:
Technical details
Here are the infrastructure changes that were needed to support TypeScript:
Compilation (Babel)
I configured Babel to use the
@babel/preset-typescript
preset, which allows Babel to compile.ts
and.tsx
files.Linting (ESLint)
I configured ESLint to used the
@babel/eslint-parser
parser, which allows ESLint to parse.ts
and.tsx
files.Testing (Jest)
I installed Jest type declarations (
@types/jest
), which provides type annotations in the test files.Documentation (Gatsby)
I configured the documentation site to use
gatsby-plugin-typescript
, which allows us to import.ts
and.tsx
files into documentation site files.Type checking and type declarations
I added a
yarn dist:types
script to type check and generate type declaration files (.d.ts
) for every TypeScript file.How to migrate a component to TypeScript
The migration process for each component may vary, but it will likely follow these high-level steps:
1. Change the file extension from
.js
to.tsx
2. Add type annotations to the component file
Here are type annotations for the
Box
component:Most Primer React components will follow a similar pattern. Each component should export a
___Props
type in addition to the default export.3. Change the file extension of tests
Next steps
Short term
Long term (after TypeScript refactor is complete)