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: Add types field to package.json #75

Closed
wants to merge 1 commit into from

Conversation

demurgos
Copy link

The upcoming TypeScript 4.5.0 version has a new stricter module resolution algorithm that more closely follows Node's resolution: node12. It requires packages to explicitly define their exported types, either with a types or export.types field in package.json.

This commit fixes the package.json so it can be consumed by projects using TypeScript 4.5.0 and the node12 resolution algorithm.

The upcoming TypeScript 4.5.0 version has a new stricter module resolution algorithm that more closely follows Node's resolution: `node12`. It requires packages to explicitly define their exported types, either with a `types` or `export.types` field in `package.json`.

This commit fixes the `package.json` so it can be consumed by projects using TypeScript 4.5.0 and the `node12` resolution algorithm.
@dougwilson
Copy link
Member

Nice, thanks for the heads up! Can you provide a link to their documentation on this change, please?

@demurgos
Copy link
Author

Here is the blog post announcing TypeScript 4.5.0 and the new resolution algorithm: https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#esm-nodejs.

I don't believe the actual details are fully documented yet: I am using the TypeScript PR directly as a reference when trying out the new mode in my projects.

I also already encountered this issue and fixed it this way for @types/koa-route.

@dougwilson
Copy link
Member

Hm, when I searched I saw that, but it seems to say it is only necessary if you don't want the default value or you are using exports, neither pf which seems to apply here. Maybe can you provide a way to replicate the non functionality? I can help add it to the test suite as well.

@demurgos
Copy link
Author

demurgos commented Oct 28, 2021

This small repo reproduces the issue: https://github.com/demurgos/raw-body-ts-node-12

Adding any of the following to raw-body's package.json fixes the issue:

  • "types": "index.d.ts"
  • "exports": {".": "./index.js"}
  • "exports": {".": {"types": "./index.d.ts", "default": "./index.js"}}

@dougwilson
Copy link
Member

Hi @demurgos and sorry I let this linger. I really appreciate your repo, because I'm not used to setting up typescript projects it is a big help. I took a look and the issue seems to be an issue with the node12 resolution system. You see, normally TypeScript will see what the imported file is for a package (using the main property from package.json, which defaults to index.js if not there) and, when there is no types there, will seek out the file:

Loading module 'raw-body' from 'node_modules' folder, target file type 'TypeScript'.
Found 'package.json' at 'raw-body-ts-node-12/node_modules/raw-body/package.json'.
'package.json' does not have a 'typesVersions' field.
File 'raw-body-ts-node-12/node_modules/raw-body.ts' does not exist.
File 'raw-body-ts-node-12/node_modules/raw-body.tsx' does not exist.
File 'raw-body-ts-node-12/node_modules/raw-body.d.ts' does not exist.
'package.json' does not have a 'typings' field.
'package.json' does not have a 'types' field.
'package.json' does not have a 'main' field.
File 'raw-body-ts-node-12/node_modules/raw-body/index.ts' does not exist.
File 'raw-body-ts-node-12/node_modules/raw-body/index.tsx' does not exist.
File 'raw-body-ts-node-12/node_modules/raw-body/index.d.ts' exist - use it as a name resolution result.
Resolving real path for 'raw-body-ts-node-12/node_modules/raw-body/index.d.ts', result 'raw-body-ts-node-12/node_modules/raw-body/index.d.ts'.

When you use node12 resolution mode, this never happens:

Explicitly specified module resolution kind: 'Node12'.
Found 'package.json' at 'raw-body-ts-node-12/package.json'.
'package.json' does not have a 'typesVersions' field.
Loading module 'raw-body' from 'node_modules' folder, target file type 'TypeScript'.
Found 'package.json' at 'raw-body-ts-node-12/node_modules/raw-body/package.json'.
'package.json' does not have a 'typesVersions' field.
'package.json' does not have a 'typings' field.
'package.json' does not have a 'types' field.
'package.json' does not have a 'main' field.
Directory 'node_modules' does not exist, skipping all lookups in it.
Directory 'C:/Users/dougw/node_modules' does not exist, skipping all lookups in it.
Directory 'C:/Users/node_modules' does not exist, skipping all lookups in it.
Directory 'C:/node_modules' does not exist, skipping all lookups in it.
File 'raw-body-ts-node-12/package.json' exists according to earlier cached lookups.
Loading module 'raw-body' from 'node_modules' folder, target file type 'JavaScript'.
File 'raw-body-ts-node-12/node_modules/raw-body/package.json' exists according to earlier cached lookups.
'package.json' does not have a 'main' field.
Directory 'node_modules' does not exist, skipping all lookups in it.

As soon as I add either "main": "index.js" or "exports": "./index.js" to the package.json, the auto file lookup functions to find the .d.ts file, even under node12:

Explicitly specified module resolution kind: 'Node12'.
Found 'package.json' at 'raw-body-ts-node-12/package.json'.
'package.json' does not have a 'typesVersions' field.
Loading module 'raw-body' from 'node_modules' folder, target file type 'TypeScript'.
Found 'package.json' at 'raw-body-ts-node-12/node_modules/raw-body/package.json'.
'package.json' does not have a 'typesVersions' field.
'package.json' does not have a 'typings' field.
'package.json' does not have a 'types' field.
'package.json' has 'main' field 'index.js' that references 'raw-body-ts-node-12/node_modules/raw-body/index.js'.
File 'raw-body-ts-node-12/node_modules/raw-body/index.js' exist - use it as a name resolution result.
File 'raw-body-ts-node-12/node_modules/raw-body/index.js' has an unsupported extension, so skipping it.
Loading module as file / folder, candidate module location 'raw-body-ts-node-12/node_modules/raw-body/index.js', target file type 'TypeScript'.
File name 'raw-body-ts-node-12/node_modules/raw-body/index.js' has a '.js' extension - stripping it.
File 'raw-body-ts-node-12/node_modules/raw-body/index.ts' does not exist.
File 'raw-body-ts-node-12/node_modules/raw-body/index.tsx' does not exist.
File 'raw-body-ts-node-12/node_modules/raw-body/index.d.ts' exist - use it as a name resolution result.
Resolving real path for 'raw-body-ts-node-12/node_modules/raw-body/index.d.ts', result 'raw-body-ts-node-12/node_modules/raw-body/index.d.ts'.

It would be reasonable to conclude here that there is a bug in the node12 resolver of typescript for the case of no main or exports in the package.json file, which is valid in the Node.js 12 resolution scheme (which is why the module is able to be imported in Node.js 12 just fine).

I hope this helps.

@dougwilson dougwilson closed this Nov 16, 2021
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.

2 participants