Skip to content
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

Fix TypeScript exports #6703

Merged
merged 5 commits into from Mar 14, 2023
Merged

Fix TypeScript exports #6703

merged 5 commits into from Mar 14, 2023

Conversation

remcohaszing
Copy link
Contributor

Which issue, if any, is this issue related to?

Closes #6694
Refs #6695 (comment)

Is there anything in the PR that needs further explanation?

The first change that was made, is that all declare module declarations were replaced. declare module is meant for declaring another module that doesn’t match the package name, for example
@types/node uses this to declare fs. To accommodate this, typeRoots was replaced with paths. Note that this change causes a lot of indentation changes, but no actual code changes.

Next up was fixing the types of stylelint. Stylelint uses module.exports =. The correct type definition for this is export =. The type definitions also export a number of types. The correct way to export types in combination with export =, is to declare a namespace.

If a namespace has no explicit exports, all members are implicitly exported. If a namespace has at least one export, all unexported members are private. I prefer the former. All exported members have been moved inside the stylelint namespace, and had their export declarations removed. All private types are kept outside of the namespace. This causes more diffs, but no type definitions have been modified.

If module.exports is a function or class, static properties are ideally declared in the namespace. However, stylelint extends postcss.PluginCreator, which has a property postcss. Because of this, the type of stylelint has been kept as-is.

This change affects all users who rely on synthetic default exports, but haven’t configured TypeScript correctly. ESM users should specify:

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true
  }
}

or better:

{
  "compilerOptions": {
    "module": "node16"
  }
}

CommonJS users who wish to use ESM syntax and transpile, should specify the following, although I personally recommend against this:

{
  "compilerOptions": {
    "esModuleInterop": true
  }
}

The correct way to consume this package using CommonJS is one of the following. This change is also reflected in the internal stylelint type annotations and type test:

// TypeScript
import * as stylelint from 'stylelint'
import stylelint = require('stylelint')

// JavaScript
const stylelint = require('stylelint')

I have some follow-up suggestions that are out of scope of this PR.

  1. Currently the tests are excluded from type checking. I recommend adding a dev dependency on @types/jest, fixing their types, and removing the exclude option from tsconfig.json.
  2. checkJs implied allowJs. I suggest to remove it.
  3. Publish the type definitions from the types folder to DefinitelyTyped. This will help others, and keep the stylelint codebase focused on stylelint.
  4. TypeScript can handle type definitions from JSDoc. This is already used for internal type checking. You may want to consider leveraging that for generating types too instead of shipping manually written type definitions.

The first change that was made, is that all `declare module`
declarations were replaced. `declare module` is meant for declaring
another module that doesn’t match the package name, for example
`@types/node` uses this to declare `fs`. To accommodate this,
`typeRoots` was replaced with `paths`. Note that this change causes a
lot of indentation changes, but no actual code changes.

Next up was fixing the types of stylelint. Stylelint uses
`module.exports =`. The correct type definition for this is `export =`.
The type definitions also export a number of types. The correct way to
export types in combination with `export =`, is to declare a namespace.

If a namespace has no explicit exports, all members are implicitly
exported. If a namespace has at least one export, all unexported members
are private. I prefer the former. All exported members have been moved
inside the `stylelint` namespace, and had their `export` declarations
removed. All private types are kept outside of the namespace. This
causes more diffs, but no type definitions have been modified.

If `module.exports` is a function or class, static properties are
ideally declared in the namespace. However, `stylelint` extends
`postcss.PluginCreator`, which has a property `postcss`. Because of
this, the type of `stylelint` has been kept as-is.

This change affects all users who rely on synthetic default exports, but
haven’t configured TypeScript correctly. ESM users should specify:

```json
{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true
  }
}
```

or better:

```json
{
  "compilerOptions": {
    "module": "node16"
  }
}
```

CommonJS users who wish to use ESM syntax and transpile, should specify
the following, although I personally recommend against this:

```json
{
  "compilerOptions": {
    "esModuleInterop": true
  }
}
```

The correct way to consume this package using CommonJS is one of the
following. This change is also reflected in the internal stylelint type
annotations and type test:

```ts
// TypeScript
import * as stylelint from 'stylelint'
import stylelint = require('stylelint')

// JavaScript
const stylelint = require('stylelint')
```
@changeset-bot
Copy link

changeset-bot bot commented Mar 12, 2023

⚠️ No Changeset found

Latest commit: a4275a3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@remcohaszing
Copy link
Contributor Author

I considered the changeset of the #6695 to be relevant to this PR, so I decided to add that back after reverting. I’m not sure if that matters. 🤔

@ybiquitous
Copy link
Member

@remcohaszing Thanks for the pull request and the follow-up suggestions! This change looks good to me. 👍🏼
Also, we would appreciate it if you could open follow-up issues or pull requests for the suggestions!

@baseballyama Could you confirm this PR can resolve your reported issue #6694?

@remcohaszing
Copy link
Contributor Author

I removed allowJs, as it’s such a small change.

I also merged the main branch, and created the following PRs to DefinitelyTyped:

@ybiquitous
Copy link
Member

ybiquitous commented Mar 13, 2023

I considered the changeset of the #6695 to be relevant to this PR, so I decided to add that back after reverting. I’m not sure if that matters. 🤔

I believe there is no problem with your decision. 👍🏼 The relevant changeset has been included already:
https://github.com/remcohaszing/stylelint/blob/fix-types/.changeset/yellow-dodos-juggle.md

@ybiquitous
Copy link
Member

Just in case, I am trying this PR's changes with my small repo. Here is:
https://github.com/ybiquitous/stylelint-pr-6695/pull/1

I believe this PR works expectedly!

Copy link
Member

@ybiquitous ybiquitous left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot! LGTM 👏🏼

They have been published to DefinitelyTyped. The published packages are
now used as dev dependencies instead.
@remcohaszing
Copy link
Contributor Author

I replaced the vendored types for postcss-media-query-parser and postcss-resolve-nested-selector with the ones published to DefinitelyTyped.

Copy link
Member

@jeddy3 jeddy3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@remcohaszing A huge thank you for the pull request and the clearly-written explanation!

@ybiquitous Thank you for creating a test repo.

LGTM. I think we can merge and include it in our 15.3.0 release.

Copy link
Member

@ybiquitous ybiquitous left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your fantastic work! 👍🏼

@jeddy3 jeddy3 merged commit 7f801dd into stylelint:main Mar 14, 2023
@remcohaszing remcohaszing deleted the fix-types branch March 14, 2023 12:36
@stof stof mentioned this pull request Mar 16, 2023
5 tasks
@baseballyama
Copy link
Contributor

Sorry for late reply.
But today I updated my Stylelint plugin and it works fine.
Thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Fix type definitions for commonjs
4 participants