TypeScript: Migrate viewport package#71118
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
manzoorwanijk
left a comment
There was a problem hiding this comment.
Is it possible to get rid of some as any assertions.
| // we are respecting that as from the static query of the HOC we generate | ||
| // a hook that calls other hooks always in the same order (because the query never changes). | ||
| // eslint-disable-next-line react-hooks/rules-of-hooks | ||
| return [ key, useViewportMatch( breakpointName, operator ) ]; | ||
| return [ | ||
| key, | ||
| // eslint-disable-next-line react-hooks/rules-of-hooks |
There was a problem hiding this comment.
Can we please move that comment above inline to the eslint rule?
There was a problem hiding this comment.
Sorry missed that, fixed ✅
…act-hooks/rules-of-hooks in with-viewport-match.ts
There was a problem hiding this comment.
Pull Request Overview
This PR migrates the viewport package from JavaScript to TypeScript as part of a broader TypeScript migration effort. The migration includes creating comprehensive type definitions for viewport queries, breakpoints, and store state management while preserving all existing functionality.
Key changes include:
- Added comprehensive TypeScript types for viewport queries, breakpoints, and store state
- Converted all JavaScript files to TypeScript with proper type annotations
- Added TypeScript configuration and project references
Reviewed Changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/viewport/tsconfig.json | New TypeScript configuration for the viewport package |
| packages/viewport/src/types.ts | Comprehensive type definitions for viewport functionality |
| packages/viewport/src/with-viewport-match.ts | Migrated HOC with proper TypeScript types and generics |
| packages/viewport/src/store/selectors.ts | Converted selectors with typed parameters and return values |
| packages/viewport/src/store/reducer.ts | Migrated reducer with proper action and state typing |
| packages/viewport/src/store/actions.ts | Converted actions with typed parameters and return values |
| packages/viewport/src/listener.ts | Migrated event listener with proper type annotations |
| packages/viewport/src/index.ts | Updated main entry point with typed constants |
| packages/viewport/src/if-viewport-matches.ts | Converted HOC with TypeScript generics and type casting |
| packages/edit-site/tsconfig.json | Added viewport package reference |
| packages/block-library/tsconfig.json | Added viewport package reference |
| packages/viewport/README.md | Updated documentation to reflect TypeScript types |
| docs/reference-guides/data/data-core-viewport.md | Updated documentation paths and type references |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| const ifViewportMatches = ( query: ViewportQuery ) => | ||
| createHigherOrderComponent( | ||
| compose( [ | ||
| ( compose as any )( [ |
There was a problem hiding this comment.
Using as any type assertion defeats the purpose of TypeScript's type safety. Consider importing compose with proper types from @wordpress/compose or defining a more specific type for this use case.
| ( compose as any )( [ | |
| compose( [ |
There was a problem hiding this comment.
We can live with it for now.
manzoorwanijk
left a comment
There was a problem hiding this comment.
This looks good to me but I would prefer other code owners to have a look as well
| const queries = Object.entries( breakpoints ).flatMap( | ||
| ( [ name, width ] ) => { | ||
| return operatorEntries.map( ( [ operator, condition ] ) => { | ||
| const queries: Array< [ string, MediaQueryList ] > = Object.entries( |
There was a problem hiding this comment.
It doesn't hurt but you don't need the type annotation here. TS can infer it easily.
| const ifViewportMatches = ( query: ViewportQuery ) => | ||
| createHigherOrderComponent( | ||
| compose( [ | ||
| ( compose as any )( [ |
There was a problem hiding this comment.
I suppose it's not easy to get rid of this assertion.
| { "path": "../data" }, | ||
| { "path": "../element" } | ||
| ], | ||
| "include": [ "src/**/*" ] |
There was a problem hiding this comment.
We don't need wildcard here.
| "include": [ "src/**/*" ] | |
| "include": [ "src" ] |
| const ifViewportMatches = ( query: ViewportQuery ) => | ||
| createHigherOrderComponent( | ||
| compose( [ | ||
| ( compose as any )( [ |
There was a problem hiding this comment.
We can live with it for now.
Co-authored-by: Manzoor Wani <manzoorwani.jk@gmail.com>
manzoorwanijk
left a comment
There was a problem hiding this comment.
This is close. Let us clean this up a bit.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 17 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * | ||
| * @return Higher-order component. | ||
| */ | ||
| const withViewportMatch = ( queries: ViewportQueries ) => { |
There was a problem hiding this comment.
The current generic typing makes the returned HOC accept the same props as the wrapped component (T), even though the HOC injects additional boolean props derived from queries. To model this correctly for consumers, consider typing withViewportMatch so the wrapped component expects OwnProps & InjectedProps, while the returned component expects only OwnProps (i.e., omit/strip the injected keys from the public props type).
There was a problem hiding this comment.
This makes sense but is not a big deal for now, but will be good to update it though.
| return createHigherOrderComponent( | ||
| < T extends Record< string, unknown > >( | ||
| WrappedComponent: ComponentType< T > | ||
| ) => { | ||
| const WrappedWithViewport = ( props: T ) => { |
There was a problem hiding this comment.
The current generic typing makes the returned HOC accept the same props as the wrapped component (T), even though the HOC injects additional boolean props derived from queries. To model this correctly for consumers, consider typing withViewportMatch so the wrapped component expects OwnProps & InjectedProps, while the returned component expects only OwnProps (i.e., omit/strip the injected keys from the public props type).
There was a problem hiding this comment.
Same about this - a nice to have.
Co-authored-by: Manzoor Wani <manzoorwani.jk@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
manzoorwanijk
left a comment
There was a problem hiding this comment.
One last bit - we need to add types field to package.json and also to exports['.'] field in it.
manzoorwanijk
left a comment
There was a problem hiding this comment.
This looks good now. Thanks
What?
Part of #67691
This PR migrates viewport package to use TypeScript
Why?
Migrating to TypeScript provides improved type-hinting in the editor & helps identify bugs early on
How?
The PR ports the existing component code to use TypeScript syntax & creates types accordingly as needed
Testing Instructions
The existing unit tests for the component should suffice