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

tsconfig module: NodeNext has typescript error TS7016 Could not find a declaration file #435

Closed
perspectivezoom opened this issue Sep 12, 2023 · 12 comments

Comments

@perspectivezoom
Copy link

perspectivezoom commented Sep 12, 2023

I'm using GridEngineHeadless to keep track of character movement serverside in a NodeJS Express Colyseus multiplayer server, and encountered the following type resolution error:

Screen Shot 2023-09-12 at 7 23 57 AM

This error does not appear on my NextJS clientside GridEngineHeadless usage (duplicating the server logic for nonlaggy local character movement).

I eventually traced the problem down to the moduleResolution: "NodeNext" config in my tsconfig.json:
Screen Shot 2023-09-12 at 7 24 21 AM
If I change the tsconfig.json to "module":"ESNext", "moduleResolution": "Node" (which is what my frontend uses), npm run build works fine.

Much Googling later, I discovered the following Typescript issue: microsoft/TypeScript#49160

Note that types corresponds to main only. main/types will be completely ignored by Node/TypeScript if exports is defined.

I've created a minimal repro at https://github.com/perspectivezoom/tsc-nodenext
Screen Shot 2023-09-12 at 8 02 48 AM
As before, changing the tsconfig.json to "module":"ESNext", "moduleResolution": "Node" causes npm run build to work.

I think the easiest bugfix here is to have the package.json exports declaration include a types path in the cjs require, but there are other ways to do it.

  "exports": {
    "require": {
      "types": "./dist/src/GridEngine.d.ts"
      "default": "./dist/GridEngine.min.cjs"
    },
    "import": "./dist/GridEngine.esm.min.js"
  },

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

Note that this is not a blocking bug; I'm using declare module "grid-engine"; in my project to bypass the error, but this workaround types GridEngineHeadless as any, which is not great.

EDIT: I am no longer using GridEngineHeadless on the serverside, because I couldn't figure out how to not drop input ticks with bad latency. Switched back to the client telling the server its position instead of inputs, which isn't great from a security perspective but not the worst thing in the world. Man, multiplayer is hard.

@Annoraaq
Copy link
Owner

I tried to reproduce the issue but for me it works as expected. But I probably did not replicate your case 100%.

I used your tsconfig.json (at least the part that you showed above) and compiled a file with the content:

import { GridEngineHeadless } from "grid-engine";

console.log(GridEngineHeadless);

That worked for me. If I change the "exports" section in Grid Engines package.json as you suggest above it breaks.

If this is still an issue for you, could you share a minimum breaking example on codesandbox or similar?

@perspectivezoom
Copy link
Author

Here you go. I made no changes other than adding a manual npm install, but I don't think I needed to do so.

Screen Shot 2023-09-17 at 8 45 11 AM

https://codesandbox.io/p/sandbox/dazzling-goldwasser-cftd8g
Not sure how long anonymous sandboxes last.
You can reproduce by visiting https://githubbox.com/perspectivezoom/tsc-nodenext (note github => githubbox domain change), going to the Terminal tab, and then converting to a cloud sandbox.

@Annoraaq
Copy link
Owner

Thanks for the example repo! I was finally able to reproduce it. However, I could not yet solve the problem with the suggested fix but I am on it.

@Annoraaq
Copy link
Owner

A small update: I think I got the types working thanks to the link to the TS docs you provided.
Now I am facing the next issue to get it running in new node versions: microsoft/TypeScript#49083

TL/DR: I will have to change all imports in the TS code to use .js file endings, even though there are no such .js files... 😭

@perspectivezoom
Copy link
Author

I will have to change all imports in the TS code to use .js file endings, even though there are no such .js files...

That is... pretty disgusting. I would rather you not do that, mostly on moral DevX grounds.

I don't know how comfortable you are with your package bundler, but outputting the d.ts files as a sibling seems to be the next best solution, if rejiggering the exports didn't work: microsoft/TypeScript#49160 (comment)

Also, this is not known widely enough: all any package author has to do is put their .d.ts files in the same directories as their .js files, just like tsc emits them by default. The only packages that are dealing with issues are ones that put their types in a separate folder for some reason. .d.ts and .js files are best friends. If you don’t separate them, you literally don’t have to put anything special at all in the package.json.

As a last resort, the other alternative I thought of was to throw up a npm install --save-dev @types/grid-engine package. It's not great, but seems barely less smelly than throwing nonexistent file.js import references.

And again, if you don't find a clean solution, feel free to close this out. It's a bit of an odd edge case.

@Annoraaq
Copy link
Owner

Annoraaq commented Sep 19, 2023

I don't know how comfortable you are with your package bundler, but outputting the d.ts files as a sibling seems to be the next best solution, if rejiggering the exports didn't work: microsoft/TypeScript#49160 (comment)

That is exactly how I finally got it working.

That is... pretty disgusting. I would rather you not do that, mostly on moral DevX grounds.

It reads like I would eventually have to do it anyway, because the TypeScript team made it pretty clear they will not allow .ts endings and I think enforcing file endings is part of the ECMA specification...

Annoraaq added a commit that referenced this issue Oct 15, 2023
Annoraaq added a commit that referenced this issue Oct 15, 2023
Annoraaq added a commit that referenced this issue Oct 15, 2023
Annoraaq added a commit that referenced this issue Oct 15, 2023
Annoraaq added a commit that referenced this issue Oct 15, 2023
Annoraaq added a commit that referenced this issue Oct 15, 2023
Annoraaq added a commit that referenced this issue Oct 15, 2023
@Annoraaq
Copy link
Owner

@perspectivezoom, can you confirm that it works now with version 2.38.0?

@perspectivezoom
Copy link
Author

Yep, I'm getting types now in the backend. It is now correctly complaining that I need to zod coerce all of my string inputs into the Direction enum now:
Screen Shot 2023-10-15 at 8 26 26 PM

I appreciate the fix @Annoraaq. Closing the issue.

@Annoraaq
Copy link
Owner

Thanks for your help and pointing it out in the first place!

@perspectivezoom
Copy link
Author

Uh oh. Bumped my nextjs frontend to 2.38.0, and now it's complaining:
Screen Shot 2023-10-16 at 7 00 53 AM

Let me know if you need a repo. For now, resolution is to keep frontend at 2.37.0

@Annoraaq Annoraaq reopened this Oct 16, 2023
Annoraaq added a commit that referenced this issue Oct 16, 2023
@Annoraaq
Copy link
Owner

I could reproduce it.

I just released a patch: v2.38.1

It now works for CJS and ESM for me.

@perspectivezoom
Copy link
Author

Confirmed that upgrading to 2.38.1 gives me types in both frontend and backend. Closing.

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

No branches or pull requests

2 participants