vite-plugin-dts icon indicating copy to clipboard operation
vite-plugin-dts copied to clipboard

Generate different declaration types

Open VividLemon opened this issue 1 year ago • 11 comments

Description

One of the differences introduced by TypeScript v5 is that .d.ts files are affected by esm and cjs contexts. So, sharing a single .d.ts file between the two can lead to invalid formats when a library is dual publishing for these contexts.

The solution is to generate .d.mts & .d.cjs files.

https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseCJS.md https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseESM.md

Under what circumstance would Vite create these wrong, I am not sure. However, for integrity, it would be best for these to be split up.

Suggested solution

Create an option to generate different, or multiple versions of the output files. It's not necessarily a requirement for the library to add specific support to generate .d.mts, .d.cts variants, but the ability to do it yourself would work.

Perhaps this is already possible through one of the included hooks. However, this I am not sure of.

Alternative

I don't really think there is an alternative.

Additional context

Alternatively/additionally, a section on the FAQ could also help.

This could also be a vue-tsc related issue, as I don't think they generate those files.

Validations

  • [X] Read the FAQ.
  • [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.

VividLemon avatar Sep 05 '23 16:09 VividLemon

I have read the information you provided, but I can't find the difference in content between .d.cts and .d.mts files. Are they just different file extensions?

qmhc avatar Sep 06 '23 02:09 qmhc

I have equally had the same questions but have found little information on what the true differences actually are syntactically. Sadly, the js ecosystem is really weird and this question is very obscure.

The only differences I can think of are the differences with how things are exported, cjs exports map to export =, mjs exports map to export {} or export default

The original issue was found when looking at https://publint.dev/rules#export_types_invalid_format

So, it is quite possible that these things are the same. But there isn't a whole lot of info. In my opinion, they are likely the same. But perhaps this is a deeper question to TypeScript as there isn't a whole lot of information on this topic.

Indeed this https://arethetypeswrong.github.io/?p=bootstrap-vue-next%400.12.0 displays that some of the issue described contain these resolution issues

VividLemon avatar Sep 06 '23 03:09 VividLemon

I found this in TypeScript docs: https://www.typescriptlang.org/docs/handbook/esm-node.html#packagejson-exports-imports-and-self-referencing.

It says: It’s important to note that the CommonJS entrypoint and the ES module entrypoint each needs its own declaration file, even if the contents are the same between them.

And I have never seen a declaration file uses export =.

So, currently we can consider they are only different in their file extensions. For this, we can add some options for custom the declaration file extensions (while considering multiple outputs with different file extensions).

qmhc avatar Sep 06 '23 08:09 qmhc

And I have never seen a declaration file uses export =.

This was a mistake. I meant to account for the differences between export default/export {} & module.exports.

So, currently we can consider they are only different in their file extensions. For this, we can add some options for custom the declaration file extensions (while considering multiple outputs with different file extensions).

This will likely work. If this is implemented, I would like to check and see what arethetypeswrong.github.io says. If it comes out with everything being clean, then imo there should likely be a section on this projects README as it should become the standard

VividLemon avatar Sep 06 '23 15:09 VividLemon

Hello, facing the exact same issue. Any updates so far?

BibiSebi avatar Oct 31 '23 09:10 BibiSebi

The way we've handled this in our company's internal component library, is to use the afterBuild hook to copy and rename the files:

import { copyFileSync } from "node:fs"

import { defineConfig } from "vite"
import dts from "vite-plugin-dts"

// https://vitejs.dev/config/
export default defineConfig({
  build: {...},
  plugins: [
    ...,
    dts({
      afterBuild: () => {
        // To pass publint (`npm x publint@latest`) and ensure the
        // package is supported by all consumers, we must export types that are
        // read as ESM. To do this, there must be duplicate types with the
        // correct extension supplied in the package.json exports field.
        copyFileSync("dist/index.d.ts", "dist/index.d.mts")
      },
      exclude: [ ... ],
      include: ["src"],
    }),
  ],
})

will-stone avatar Oct 31 '23 11:10 will-stone

One small change to make publint happy. Change to copyFileSync("dist/index.d.ts", "dist/index.d.cts"); and have your package.json exports look something like:

"exports": {
    ".": {
      "import": {
        "types": "./dist/index.d.ts",
        "default": "./dist/main.js"
      },
      "require": {
        "types": "./dist/index.d.cts",
        "default": "./dist/main.cjs"
      }
    }
  },

Specifically, the CJS types need to use the .cts extension rather than having a .mts extension for ESM, at least when you're using "type": "module".

mkilpatrick avatar Dec 04 '23 16:12 mkilpatrick

@mkilpatrick yes! I had to do that version when converting to proper esm-first.

will-stone avatar Dec 04 '23 18:12 will-stone

And I have never seen a declaration file uses export =.

If I only have a default export attw complains about node16 (from CJS) │ ❗️ Incorrect default export. If I modify the .d.cts file's export default MyDefaultExportedFn to export = MyDefaultExportedFn then the error goes away.

Or as an odd workaround, if I add an extra export, next to the default export, then the error also goes away in attw

Juice10 avatar Apr 16 '24 22:04 Juice10