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
Add TypeScript type definitions #5582
Conversation
Fixes #5580 - Types are refactored to be exportable and are now provided in the package: - `Stylelint` prefix removed where appropriate, types namespaced under `stylelint`. - Module export definition changed to point to namespace and public API, which allows `require('stylelint')` to be typed correctly. - Types renamed to match those in the `@types/stylelint` package to reduce incompatibilities/breakages downstream. - As a result of these changes, the separate types package can be deprecated in favour of the built-in type definitions. - Internal API endpoints marked with `@internal` where appropriate. - PostCSS types in types definition file scoped under `PostCSS` (e.g. `PostCSS.Root`) to make it clearer which types are imported. - API types (`stylelint.lint`, `stylelint.createPlugin`, etc.) changed from `Function` to more specific types that actually reflect each function's signature. - Refactored export types in public-facing exports (e.g. `lib/index.js`, `lib/createPlugin.js`) to reference API types in type definition file. This ensures that Typescript will report errors if the implementation/ internal type annotations are changed to an incompatible signature. Any types that were only defined in those files as `@typedef` JSDoc comments have been moved to the `.d.ts` definition file. - Fixed problem with `Rule` types that resulted in Typescript errors when using `createPlugin`. Required properties were added in #5418, which broke usage of `createPlugin` as the `rule` parameter would require functions to have the newly added properties, even though this doesn't reflect the implementation accurately. To fix this: - `Rule` type split into `RuleBase` and `Rule`. Added the `Plugin` type as an alias for `RuleBase` to achieve parity with former types at `@types/stylelint`. `RuleBase` represents the rule without any properties attached. `Rule` is a union of `RuleBase` and an object with the properties. - `createPlugin` updated to use `RuleBase`. - Fixed Typescript errors being thrown when the configs passed to the `overrides` option would contain supported properties that were missing from the types definition: - `ConfigOverride` type updated to use `Omit` instead of `Pick`, removing the `overrides` property instead of allow-listing properties. This fix means the `ConfigOverride` type shouldn't need to be manually updated whenever a new configuration property is added. - `RuleMessages` and related types fixed to avoid Typescript errors. The return type of `stylelint.utils.ruleMessages` was incorrectly set to the type of the `messages` parameter, which resulted in type errors in `lib/ruleMessages.js`. This change: - Changes the `ruleMessages` return type to `{ [K in keyof T]: T[K] }` which is correct. There is a distinction between returning the same type as being passed to the function and returning a type with the same keys and value types for those keys. - `RuleMessages` type changed to a mapped type to facilitate the change to `stylelint.utils.ruleMessages`. This allows Typescript to narrow types for the object returned by `ruleMessages`: ```js const messages = stylelint.utils.ruleMessages(ruleName, { violation: 'This a rule violation message', warning: (reason: string) => `This is not allowed because ${reason}`, }); // If a `Record<...>` was used instead, the following lines would // result in Typescript error 2322. const violationMessage: string = messages.violation; const violationFunc: Function = messages.warning; ``` - Type annotations in `lib/ruleMessages.js` updated to refect these changes and to avoid Typescript errors and allow type-checking. - Type test file added to `types/stylelint/type-test.ts`. This file contains code that references the public API as a consuming package would use it. It is not executed, but is used so that if the API or types are changed in a breaking way, the change will be caught by Typescript. If this existed before, the breaking change to the `StylelintRule` type (now `stylelint.Rule`) would have been caught. - Documentation comments added to public API endpoints (`stylelint.*`). - Removed leftover duplicate `Options` type that had no references anywhere in the project.
Updated PR comment with links to each relevant change in the code, where appropriate. |
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.
Terrific!
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.
@adalinesimonian Fantastic! Thank you so much for your work! 👏🏼
This change will expose Stylelint's type definition, so I suggest:
- rename this PR title (
refactor
seems confusing) - include this change to the 14.0.0 release note as a new feature
- close the Create TypeScript definitions #4399 issue
@ybiquitous I've renamed the PR, linked #4399 to it, and added a note to the changelog in aa98de1 |
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.
Amazing work, thank you!
Suggested a minor typo change.
As per #5205 (comment), should we add a note to the migration guide? Something at the bottom along the lines of:
Integration authors
TypeScript type definitions are now exported in the stylelint
package. If you use the @types/stylelint
package, you should remove it from your dependencies.
@jeddy3 Fixed the typo and added a note about types to the migration guide. |
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.
Thanks for making the changes!
LGTM.
* refactor: use upstream types directly w/o script Made possible by stylelint/stylelint#5582 * fix: avoid typescript error, conform to new types Disables are no longer reported directly on results and are now reported just like other rules.
`stylelint@14.0.0` has added its type definitions. See below: - https://github.com/stylelint/stylelint/releases/tag/14.0.0 - stylelint/stylelint#5582
Closes #4399, Fixes #5580
Types are refactored to be exportable and are now provided in the package:
Stylelint
prefix removed where appropriate, types namespaced understylelint
.Module export definition changed to point to namespace and public API, which allows
require('stylelint')
to be typed correctly.Types renamed to match those in the
@types/stylelint
package to reduce incompatibilities/breakages downstream.As a result of these changes, the separate types package can be deprecated in favour of the built-in type definitions.
Internal API endpoints marked with
@internal
where appropriate.PostCSS types in types definition file scoped under
PostCSS
(e.g.PostCSS.Root
) to make it clearer which types are imported (example).API types (
stylelint.lint
,stylelint.createPlugin
, etc.) changed fromFunction
to more specific types that actually reflect each function's signature.Refactored export types in public-facing exports (e.g.
lib/index.js
,lib/createPlugin.js
) to reference API types in type definition file. This ensures that Typescript will report errors if the implementation/internal type annotations are changed to an incompatible signature. Any types that were only defined in those files as@typedef
JSDoc comments have been moved to the.d.ts
definition file (for example, theViolation
type).Fixed problem with
Rule
types that resulted in Typescript errors when usingcreatePlugin
. Required properties were added in Improve types forat-rule-*
rules #5418, which broke usage ofcreatePlugin
as therule
parameter would require functions to have the newly added properties, even though this doesn't reflect the implementation accurately. To fix this:Rule
type split intoRuleBase
andRule
. Added thePlugin
type as an alias forRuleBase
to achieve parity with former types at@types/stylelint
.RuleBase
represents the rule without any properties attached.Rule
is a union ofRuleBase
and an object with the properties.createPlugin
updated to usePlugin
.Fixed Typescript errors being thrown when the configs passed to the
overrides
option would contain supported properties that were missing from the types definition:ConfigOverride
type updated to useOmit
instead ofPick
, removing theoverrides
property instead of allow-listing properties. This fix means theConfigOverride
type shouldn't need to be manually updated whenever a new configuration property is added.RuleMessages
and related types fixed to avoid Typescript errors. The return type ofstylelint.utils.ruleMessages
was incorrectly set to the type of themessages
parameter, which resulted in type errors inlib/ruleMessages.js
. This change:Changes the
ruleMessages
return type to{ [K in keyof T]: T[K] }
, which is correct. There is a distinction between returning the same type as being passed to the function and returning a type with the same keys and value types for those keys.RuleMessages
type changed to a mapped type to facilitate the change tostylelint.utils.ruleMessages
. This allows Typescript to narrow types for the object returned byruleMessages
:Type annotations in
lib/utils/ruleMessages.js
updated to refect these changes and to avoid Typescript errors and allow type-checking.Type test file added to
types/stylelint/type-test.ts
. This file contains code that references the public API as a consuming package would use it. It is not executed, but is used so that if the API or types are changed in a breaking way, the change will be caught by Typescript. If this existed before, the breaking change to theStylelintRule
type (nowstylelint.Rule
) would have been caught.Documentation comments added to public API endpoints (
stylelint.*
).Removed leftover duplicate
Options
type that had no references anywhere in the project.