Improve types#555
Conversation
WalkthroughThe pull request introduces new types and modifies existing exported entities in the Changes
Suggested reviewers
Poem
Tip ⚡🧪 Multi-step agentic review comment chat (experimental)
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
⏰ Context from checks skipped due to timeout of 90000ms (20)
🔇 Additional comments (5)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
| export const rules: Record<string, unknown> | ||
| export const rules: Configuration['module']['rules'] |
There was a problem hiding this comment.
This type was wrong, it's an array.
There was a problem hiding this comment.
Good catch, not sure why I typed this as a Record - however, these types are wrong:
Configuration['module']is optional, so you need to wrap withRequired<Configuration>- The types for webpack tend to be very loose, allowing a lot of different "conditional" values like empty strings and
false, but we know specifically what our values are so it would be better to useRuleSetRule[]
For reference, this is the type of Required<Configuration>['module']:
interface ModuleOptions {
// ...
rules?: (undefined | null | false | "" | 0 | RuleSetRule | "...")[];
// ...
}
There was a problem hiding this comment.
but we know specifically what our values are so it would be better to use
RuleSetRule[]
I missed that it was exported, fixed.
| [K in keyof T as CamelToSnakeCase<string & K>]: T[K]; | ||
| } | ||
|
|
||
| type DevServerConfig = SnakeCase<Omit<WebpackDevServerConfiguration, 'hot'>> & { |
There was a problem hiding this comment.
Translates e.g. allowedHosts to allowed_hosts.
| "@babel/preset-env": "^7.16.11", | ||
| "@babel/runtime": "^7.17.9", | ||
| "@types/babel__core": "^7.0.0", | ||
| "@types/webpack": "^5.0.0", |
There was a problem hiding this comment.
Types are now included in Webpack itself.
f2e9fe8 to
d67155c
Compare
| "@types/webpack-dev-middleware": "5.0.2", | ||
| "@types/webpack-dev-server": "4.5.1", |
There was a problem hiding this comment.
These are older versions, but ones which don't pull the main packages. And since they are devDependencies, the clients aren't bound to them in any way.
There was a problem hiding this comment.
Why are these here at all, given we've already got both of these libs in the tree and they're shipping with their own types? if we're expecting to be compatible with these versions, then we should specify them as optional peer dependencies, otherwise we shouldn't need to include these dependencies (and optionally include both packages as dev dependencies, which shouldn't be an issue as they're already in the tree - though since we're not authoring in TypeScript or doing any type checking ourselves in CI, I don't think it'd be a big deal if we omitted webpack-dev-middleware)
There was a problem hiding this comment.
given we've already got both of these libs in the tree
I only added @types/webpack-dev-server because we didn't:
02:35:03 ~/shaka/shakapacker (alexeyr/improve-types)$ yarn why webpack-dev-server
yarn why v1.22.22
[1/4] Why do we have the module "webpack-dev-server"...?
[2/4] Initialising dependency graph...
[3/4] Finding dependency...
error We couldn't find a match!
Done in 0.18s.
02:35:12 ~/shaka/shakapacker (alexeyr/improve-types)$ yarn why webpack-dev-middleware
yarn why v1.22.22
[1/4] Why do we have the module "webpack-dev-middleware"...?
[2/4] Initialising dependency graph...
[3/4] Finding dependency...
error We couldn't find a match!
Done in 0.16s.
and @types/webpack-dev-middleware version is specified because otherwise @types/webpack-dev-server pulls in a later version which is really the whole webpack-dev-middleware.
There was a problem hiding this comment.
Ah right ok well that's a mistake - we should have webpack-dev-server v4.9 as a dev dependency
There was a problem hiding this comment.
I can add it instead of @types/webpack-dev-server then. Would it only be used for the types, though, or do you have something else in mind?
There was a problem hiding this comment.
Technically we should be using it since it's specified as a peer dependency and we should be satisfying our own constraints, though in reality it's not needed because our test suite is based around generating dummy projects which include adding this dependency.
Frankly, we could just continue on omitting it for now since we're not doing anything with these types in CI either - I'm fine with either, but my point is based on that regardless of if you're using it for types or runtime stuff, as its listed as a peer dependency it's fair to assume webpack-dev-server is available and that includes for ourselves so if you need it add it
There was a problem hiding this comment.
Since we've decided to duplicate the types anyway, it's moot and we don't need to change package.json at all (except for maybe removing @types/webpack from peer dependencies).
ff08f18 to
6a4c4f0
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
CHANGELOG.md (1)
17-20: Document New "Fixed" Section for Improved Type DefinitionsThe new "### Fixed" section entry documenting the enhanced type precision for
devServerandrules(PR 555) is clear and aligns well with the PR's objectives.Note: According to markdownlint (MD004), it is recommended to use asterisks (*) instead of dashes (-) for unordered list items. Consider updating the bullet style in this section for consistency.
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
19-19: Unordered list style
Expected: asterisk; Actual: dash(MD004, ul-style)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (3)
CHANGELOG.md(1 hunks)package.json(1 hunks)package/index.d.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- package.json
- package/index.d.ts
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
CHANGELOG.md
15-15: Unordered list style
Expected: asterisk; Actual: dash
(MD004, ul-style)
19-19: Unordered list style
Expected: asterisk; Actual: dash
(MD004, ul-style)
6a4c4f0 to
fc5209f
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
CHANGELOG.md (3)
9-10: Clarify the New 'Versions' SectionA new "# Versions" header has been introduced to separate version-related notes. Verify that this addition aligns with the overall changelog structure and naming conventions used in previous releases.
13-16: Document 'Changed' Updates with Core-js Version ImprovementThe "### Changed" section effectively records the update regarding using the current
core-jsversion fromnode_modules. However, the bullet item on line 15 uses a dash (-) while markdownlint recommends using an asterisk (*). For consistency with MD004, please consider updating the bullet style.🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
15-15: Unordered list style
Expected: asterisk; Actual: dash(MD004, ul-style)
17-20: Document 'Fixed' Updates for Type PrecisionThe "### Fixed" section notes the enhancement for more precise types for
devServerandrulesin the configuration. Similar to the "Changed" bullet, the list item on line 19 uses a dash (-). To comply with the markdownlint guideline (MD004), please consider revising the bullet indicator to an asterisk (*).🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
19-19: Unordered list style
Expected: asterisk; Actual: dash(MD004, ul-style)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (3)
CHANGELOG.md(1 hunks)package.json(1 hunks)package/index.d.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- package.json
- package/index.d.ts
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
CHANGELOG.md
15-15: Unordered list style
Expected: asterisk; Actual: dash
(MD004, ul-style)
19-19: Unordered list style
Expected: asterisk; Actual: dash
(MD004, ul-style)
⏰ Context from checks skipped due to timeout of 90000ms (20)
- GitHub Check: Testing (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.6.1.x)
- GitHub Check: Testing (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Testing (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.6.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.4, gemfiles/Gemfile-rails.8.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.8.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.6.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.6.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.6.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.8.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.6.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.6.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.7.1.x)
|
Note after applying this change to a project, I'm getting some errors that I've actually never seen before in TypeScript: I'll do some more digging into what's happening, but I think it would be worth holding off landing this until this error is understood more; it might be worth cherry-picking some of these changes in the meantime e.g. the |
fc5209f to
3d007f3
Compare
|
Seems to be reasonably well described in https://stackoverflow.com/questions/78907286/why-won-t-typescript-let-me-import-a-type-from-an-es-module-into-a-commonjs-modu. The fix suggested there requires TS 5.3, and I don't know how safe it's to expect everywhere. Can you check if adding According to https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html, there is also a workaround supported from TS 4.7 and I think that's safe to assume. But I'm not sure about its implications.
The major benefit of using the package types is that we'd get the correct properties for the |
Yup I'd seen that but didn't have time to dig further into it or give it a try, and I believe it needs to be at the import site where the error is raised. While I'm still not in a good position to dig deeper, I have been able to confirm that last point i.e. adding the |
I misread the error message. Yes, probably better to duplicate and say that it depends on webpack-dev-server version then. |
46bafcc to
e2cc49b
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
package/index.d.ts (1)
47-69: Comprehensive type definitions for dev server configuration.The
DevServerConfiginterface provides much more precise typing compared to the previousRecord<string, unknown>. Some properties still use genericRecord<string, unknown>types where more specific types could be used.Consider further improving the type precision for properties like
client,dev_middleware, andproxyby either:
- Importing their specific types from webpack-dev-server
- Defining more specific interfaces based on the webpack-dev-server documentation
For example:
client?: { logging?: 'none' | 'error' | 'warn' | 'info' | 'log' | 'verbose'; overlay?: boolean | { errors?: boolean; warnings?: boolean }; progress?: boolean; webSocketURL?: string | { hostname?: string; pathname?: string; port?: string; protocol?: string }; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
package/index.d.ts(2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (19)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.6.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.4, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.8.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.6.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.6.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.6.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.6.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.6.1.x)
- GitHub Check: test
🔇 Additional comments (6)
package/index.d.ts (6)
2-3: Good addition of specific type imports.The imports for
RuleSetRulefrom webpack and the Node.jshttpsmodule provide the necessary type definitions for the more specific types being introduced in this PR.
36-38: Well-defined utility types for the dev server config.These types provide clear definitions for headers, server types, and WebSocket types, which will make the dev server configuration more type-safe.
40-46: Clear documentation of the dev server configuration behavior.The JSDoc comment effectively explains the relationship between this interface and webpack-dev-server's configuration, highlighting the key differences (snake_case property names and
hmrinstead ofhot).
72-72: Improved type precision for devServer export.Updating the type from
Record<string, unknown>to the more specificDevServerConfiginterface greatly improves type safety and developer experience.
76-76: Correct fix for rules export type.Changing from
Record<string, unknown>toRuleSetRule[]properly reflects that rules is an array of webpack rules rather than a record object.
40-69:Details
❓ Verification inconclusive
Be aware of potential TypeScript module resolution issues.
Based on the PR comments, there were concerns about TypeScript errors related to ESM imports from CommonJS modules. While this declaration file doesn't directly address those issues, be mindful that consumers of this package might face compatibility issues with webpack-dev-server types depending on their TypeScript version.
If you're planning to use types from webpack-dev-server directly in the future, consider:
- Adding conditional type resolution for different TypeScript versions
- Documenting any minimum TypeScript version requirements
- Duplicating necessary types to avoid direct dependencies on potentially problematic imports
🌐 Web query:
TypeScript module resolution ESM from CommonJS error TS1542💡 Result:
When encountering TypeScript error TS1542 ("An import path cannot end with a '.ts' extension") while importing ES modules (ESM) from CommonJS (CJS), the core issue stems from conflicting module systems and resolution strategies. Here's how to resolve it:
Key Problem
TypeScript enforces output file safety by default:
- CJS projects using
require()can't directly import ESM files (must use dynamicimport())- File extensions must match the output JS format (
.jsinstead of.tsin imports) [1][5]Solutions
1. For CJS-to-ESM Interop:
// Use dynamic imports for ESM modules in CJS const { esmFunction } = await import('./esm-module.js');2. Configure tsconfig.json:
{ "compilerOptions": { "module": "NodeNext", // or "ESNext" for pure ESM "moduleResolution": "NodeNext", "allowImportingTsExtensions": true, // If using .ts imports "esModuleInterop": true // Critical for CJS/ESM interop } }3. File Extension Handling:
// Always include .js extensions for ESM imports import { helper } from './utils.js'; // Output extension, not .tsCommon Pitfalls & Fixes
Issue Solution Mixing CJS/ESM in same project Use "type": "module"in package.json + dynamic imports for CJS [5][9]Third-party ESM packages Enable esModuleInterop+ verify package exports [8][9]Node.js runtime errors Use --experimental-vm-modulesflag for ESM tests [7][9]Bundler configurations Set moduleResolution: "bundler"for webpack/Rollup [1][5]Recommended Workflow
- Explicit Extensions: Always write imports with
.jsextensions, even for.tsfiles [1][5]- Module Boundary: Separate ESM/CJS codebases when possible
- Build Tools: Use
tsuporrollupwith dual CJS/ESM output [5][7]- Type Checking: Enable
skipLibCheck: falsefor strict validation [6][12]For library authors, include both build formats:
// package.json { "exports": { ".": { "import": "./dist/esm/index.js", "require": "./dist/cjs/index.js" } } }Critical Note: The
nodenext/node16resolutions require strict ESM compliance in Node.js environments, whilebundlermode offers more flexibility for frontend tools [1][4][5]. Always match yourmoduleandmoduleResolutionsettings to the target runtime environment.Citations:
- 1: https://www.typescriptlang.org/docs/handbook/modules/theory.html
- 2: https://www.typescriptlang.org/docs/handbook/modules/appendices/esm-cjs-interop.html
- 3: dcodeIO/long.js#125
- 4: https://www.typescriptlang.org/tsconfig/moduleResolution.html
- 5: https://evertpot.com/universal-commonjs-esm-typescript-packages/
- 6: https://intellij-support.jetbrains.com/hc/en-us/community/posts/360008176680-Webstorm-not-resolving-module-imports-using-typescript-paths
- 7: https://mikebian.co/converting-a-node-project-from-commonjs-to-esm/
- 8: https://community.prismic.io/t/typescript-error-regarding-prismicio-client-after-switching-module-resolution-in-typescript/13154
- 9: https://dev.to/a0viedo/nodejs-typescript-and-esm-it-doesnt-have-to-be-painful-438e
- 10: kulshekhar/ts-jest#4521
- 11: https://mgregersen.dk/converting-a-typescript-project-from-cjs-to-esm-the-ultimate-how-to/
- 12: https://developercommunity.visualstudio.com/content/problem/599902/typescript-does-not-resolve-module-typings-in-node.html
- 13: SBoudrias/Inquirer.js#1199
- 14: microsoft/TypeScript#58658
ACTION REQUIRED: Verify TypeScript Module Resolution Settings
The changes in
package/index.d.ts(lines 40–69) correctly update the webpack-dev-server configuration keys but do not address potential interop issues—specifically, the TS1542 errors arising when consumers import ESM modules from a CommonJS context. While this file isn’t designed to solve these issues, please note the following recommendations for future-proofing:
- Conditional Type Resolution: If you plan to reference webpack-dev-server types directly, consider implementing conditional types or duplicating essential type definitions to decouple from problematic external dependencies.
- Documentation Updates: Clearly document the supported TypeScript versions and required
tsconfig.jsonsettings (for example, ensuring settings like"module": "NodeNext","moduleResolution": "NodeNext", and"esModuleInterop": trueare appropriately configured) to help consumers avoid TS1542-related issues.- Consumer Guidance: Advise users of this package to verify and adjust their TypeScript configurations if they encounter module resolution errors, especially when mixing ESM and CommonJS modules.
Summary
More precise types in
package/index.d.tsPull Request checklist
[ ] Add/update test to cover these changes[ ] Update documentationSummary by CodeRabbit
New Features
Refactor
Documentation