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(tscjs): fix typescript in cjs builds by using a separate type import #2935

Merged
merged 13 commits into from
Oct 13, 2023

Conversation

djMax
Copy link
Contributor

@djMax djMax commented Oct 11, 2023

Closes #2356

Taking this PR from another project as inspiration:
openapi-ts/openapi-typescript#1360

This should fix ariakit-react typing in Typescript projects using NodeNext module/moduleresolution by explicitly pointing at a "cts" type definition file. It should not bother existing use cases but I left index.d.ts in the cjs module just in case.

@changeset-bot
Copy link

changeset-bot bot commented Oct 11, 2023

🦋 Changeset detected

Latest commit: 009982b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@ariakit/core Patch
@ariakit/react Patch
@ariakit/react-core Patch
@ariakit/test Patch

Not sure what this means? Click here to learn what changesets are.

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

@vercel
Copy link

vercel bot commented Oct 11, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
ariakit ✅ Ready (Inspect) Visit Preview Oct 13, 2023 9:58pm
1 Ignored Deployment
Name Status Preview Updated (UTC)
reakit ⬜️ Ignored (Inspect) Visit Preview Oct 13, 2023 9:58pm

@vercel
Copy link

vercel bot commented Oct 11, 2023

@djMax is attempting to deploy a commit to the Ariakit Team on Vercel.

A member of the Team first needs to authorize it.

@codesandbox-ci
Copy link

codesandbox-ci bot commented Oct 11, 2023

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 009982b:

Sandbox Source
Ariakit Configuration

@diegohaz
Copy link
Member

Hi, @djMax. Thanks for the PR! Could you please create a reproduction of the issue this PR resolves?

Comment on lines 50 to 61
if (includeTypes) {
return {
import: {
default: `./${join(esmDir, path)}.js`,
types: `./${join(cjsDir, path)}.d.ts`,
},
require: {
default: `./${join(cjsDir, path)}.cjs`,
types: `./${join(cjsDir, path)}.d.cts`,
},
};
}
Copy link
Member

Choose a reason for hiding this comment

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

According to the TypeScript documentation, the types field should be listed first. However, the documentation also notes that it will search for a declaration file in the same location. So, I'm curious whether it's necessary to explicitly set it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is. But I could certainly flip the order. In terms of repro, should I do that just as a separate git repo or is there a more typical place to do that in ariakit? i.e. do we use stackblitz or some similar thing.

Copy link
Member

Choose a reason for hiding this comment

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

It is.

Is it still necessary if you remove the .d.ts files from the folder, only leaving the .d.cts ones?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we only had the .d.cts, then we wouldn't be pointing to in properly in the global "types" key. All of this is premised on the idea that upstream users of ariakit should not be forced into type: module, as evidenced by the multiple build outputs and the multiple import paths. This PR just fixes that to include Typescript situations that do not rely on ESM.

@djMax
Copy link
Contributor Author

djMax commented Oct 11, 2023

@diegohaz
Copy link
Member

https://stackblitz-starters-j4p32y.stackblitz.io

Thanks! I couldn't access that page, but I could see the source code when I changed the URL to https://stackblitz.com/edit/stackblitz-starters-j4p32y.

Looks like there's no "type": "module" in the package.json file. What's the use case for using "moduleResolution": "NodeNext" in a CommonJS project?

@djMax
Copy link
Contributor Author

djMax commented Oct 11, 2023

Because, like many people, we rely on things that cannot handle type: module just yet. ESM is a s**t show, we don't want ariakit being the thing forcing people to endure the pain (IMHO).

@diegohaz
Copy link
Member

I understand not every project can be ESM right now. And Ariakit doesn't force this option. My question was about using "moduleResolution": "NodeNext" rather than "moduleResolution": "Node" (where this problem doesn't exist) in a CommonJS project. Is there a use case for that?

@djMax
Copy link
Contributor Author

djMax commented Oct 11, 2023

The short answer is I'm not sure. The longer one is that I think all modern large projects seem to balance on the head of a pin with ESM: between Next.js, Typescript, Vitest, Jest, sindresorhus's refusal to do anything except ESM, webpack, Storybook, etc. So it is a supported setting (NodeNext for module/moduleResolution) and working for us everywhere, EXCEPT that for some reason Typescript gets confused about the exports if there is no separate type detail in the export key in package.json. I cannot begin to fathom all the intricacies of why or why our pin is not currently poking us in the eye.

Copy link
Member

@diegohaz diegohaz left a comment

Choose a reason for hiding this comment

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

I've updated the build script to copy all CJS declaration files to their corresponding .d.cts versions, so it also works with deep path imports. I tested locally with various combinations of type, module, and moduleResolution values, and everything appears to be functioning well.

@diegohaz diegohaz enabled auto-merge (squash) October 13, 2023 21:59
@diegohaz diegohaz merged commit 5b6ce47 into ariakit:main Oct 13, 2023
16 checks passed
@github-actions github-actions bot mentioned this pull request Oct 13, 2023
diegohaz pushed a commit that referenced this pull request Oct 14, 2023
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @ariakit/core@0.3.4

### Patch Changes

- [`#2935`](#2935) Fixed
TypeScript declaration files in CommonJS projects using `NodeNext` for
`moduleResolution`.

- [`#2945`](#2945) Added new
`disabledFromProps` function to `@ariakit/core/utils/misc`.

- [`#2948`](#2948) Added `"use
client"` directive to all modules.

-   Improved JSDocs.

## @ariakit/react@0.3.5

### Patch Changes

- [`#2935`](#2935) Fixed
TypeScript declaration files in CommonJS projects using `NodeNext` for
`moduleResolution`.

- [`#2945`](#2945) Added `name`
and `value` properties to non-native input elements rendered by
[`Checkbox`](https://ariakit.org/reference/checkbox),
[`Radio`](https://ariakit.org),
[`MenuItemCheckbox`](https://ariakit.org/reference/menu-item-checkbox),
and [`MenuItemRadio`](https://ariakit.org/reference/menu-item-radio).

It's now possible to access the `name` and `value` properties from the
`event.target` element in the
[`onChange`](https://ariakit.org/reference/checkbox#onchange) event
handler.

- [`#2945`](#2945) Fixed
[`CompositeItem`](https://ariakit.org/reference/composite-item) and
associated components not receiving the
[`disabled`](https://ariakit.org/reference/composite-item#disabled) prop
when it's being used by a higher-level component such as
[`MenuItemCheckbox`](https://ariakit.org/reference/menu-item-checkbox)
or [`MenuItemRadio`](https://ariakit.org/reference/menu-item-radio).

- [`#2945`](#2945) It's now
possible to control the menu
[`values`](https://ariakit.org/reference/menu-provider#values) state by
passing the
[`checked`](https://ariakit.org/reference/menu-item-checkbox#checked),
[`defaultChecked`](https://ariakit.org/reference/menu-item-checkbox#defaultchecked)
and
[`onChange`](https://ariakit.org/reference/menu-item-checkbox#onchange)
props to
[`MenuItemCheckbox`](https://ariakit.org/reference/menu-item-checkbox)
and [`MenuItemRadio`](https://ariakit.org/reference/menu-item-radio).

- [`#2948`](#2948) Added `"use
client"` directive to all modules.

- [`#2949`](#2949) The
[Select](https://ariakit.org/components/select) component will now
display the selected option(s) on the underlying native select element
even when the corresponding
[`SelectItem`](https://ariakit.org/reference/select-item) components
aren't rendered.

This comes in handy when the
[`SelectPopover`](https://ariakit.org/reference/select-popover)
component is rendered dynamically (for instance, using the
[`unmountOnHide`](https://ariakit.org/reference/select-popover#unmountonhide)
prop) or a
[`defaultValue`](https://ariakit.org/reference/select-provider#defaultvalue)
is given without a matching
[`SelectItem`](https://ariakit.org/reference/select-item) component.

-   Improved JSDocs.

-   Updated dependencies: `@ariakit/react-core@0.3.5`.

## @ariakit/react-core@0.3.5

### Patch Changes

- [`#2935`](#2935) Fixed
TypeScript declaration files in CommonJS projects using `NodeNext` for
`moduleResolution`.

- [`#2945`](#2945) Added `name`
and `value` properties to non-native input elements rendered by
[`Checkbox`](https://ariakit.org/reference/checkbox),
[`Radio`](https://ariakit.org),
[`MenuItemCheckbox`](https://ariakit.org/reference/menu-item-checkbox),
and [`MenuItemRadio`](https://ariakit.org/reference/menu-item-radio).

It's now possible to access the `name` and `value` properties from the
`event.target` element in the
[`onChange`](https://ariakit.org/reference/checkbox#onchange) event
handler.

- [`#2945`](#2945) Fixed
[`CompositeItem`](https://ariakit.org/reference/composite-item) and
associated components not receiving the
[`disabled`](https://ariakit.org/reference/composite-item#disabled) prop
when it's being used by a higher-level component such as
[`MenuItemCheckbox`](https://ariakit.org/reference/menu-item-checkbox)
or [`MenuItemRadio`](https://ariakit.org/reference/menu-item-radio).

- [`#2945`](#2945) It's now
possible to control the menu
[`values`](https://ariakit.org/reference/menu-provider#values) state by
passing the
[`checked`](https://ariakit.org/reference/menu-item-checkbox#checked),
[`defaultChecked`](https://ariakit.org/reference/menu-item-checkbox#defaultchecked)
and
[`onChange`](https://ariakit.org/reference/menu-item-checkbox#onchange)
props to
[`MenuItemCheckbox`](https://ariakit.org/reference/menu-item-checkbox)
and [`MenuItemRadio`](https://ariakit.org/reference/menu-item-radio).

- [`#2948`](#2948) Added `"use
client"` directive to all modules.

- [`#2949`](#2949) The
[Select](https://ariakit.org/components/select) component will now
display the selected option(s) on the underlying native select element
even when the corresponding
[`SelectItem`](https://ariakit.org/reference/select-item) components
aren't rendered.

This comes in handy when the
[`SelectPopover`](https://ariakit.org/reference/select-popover)
component is rendered dynamically (for instance, using the
[`unmountOnHide`](https://ariakit.org/reference/select-popover#unmountonhide)
prop) or a
[`defaultValue`](https://ariakit.org/reference/select-provider#defaultvalue)
is given without a matching
[`SelectItem`](https://ariakit.org/reference/select-item) component.

-   Improved JSDocs.

-   Updated dependencies: `@ariakit/core@0.3.4`.

## @ariakit/test@0.3.1

### Patch Changes

- [`#2935`](#2935) Fixed
TypeScript declaration files in CommonJS projects using `NodeNext` for
`moduleResolution`.

- [`#2948`](#2948) Added `"use
client"` directive to all modules.

-   Updated dependencies: `@ariakit/core@0.3.4`.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@djMax
Copy link
Contributor Author

djMax commented Oct 14, 2023

Excellent, that is definitely better, so I appreciate it!

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

Successfully merging this pull request may close these issues.

Can't find types with moduleResolution=nodeNext
2 participants