Open trinitrotoluene opened 3 years ago
The --files
option might fix this, I'm not sure.
https://typestrong.org/ts-node/docs/options https://typestrong.org/ts-node/docs/types
You can also try adding a triple-slash reference directive in the files that rely on cheerio types. Typically TS knows to look at types because you import
them. In cases where you do not import
them, but still want the compiler to understand they exist, you can /// <reference>
them.
I apologise, that was a mistake in my reproduction script- the error persists with import cheerio from 'cheerio';
in index.ts
, I've pushed those changes to make that clear.
I've also tried the --files
flag but it doesn't seem to make a difference, I get exactly the same error.
Additionally, I thought I'd add (just to rule out that it's a problem with mocha) that the reproduction command uses mocha but you can get the same error by just running ts-node directly (this is with the explicit import and --files specified):
PS C:\Users\trinitrotoluene\WebstormProjects\ts-node-repro\b\btest> npx ts-node -r tsconfig-paths/register .\b.spec.ts
C:\Users\trinitrotoluene\WebstormProjects\ts-node-repro\b\btest\node_modules\ts-node\src\index.ts:587
return new TSError(diagnosticText, diagnosticCodes);
^
TSError: ⨯ Unable to compile TypeScript:
../../a/liba/index.ts:3:28 - error TS2503: Cannot find namespace 'cheerio'.
3 export const repro = (foo: cheerio.Root) => {
~~~~~~~
at createTSError (C:\Users\trinitrotoluene\WebstormProjects\ts-node-repro\b\btest\node_modules\ts-node\src\index.ts:587:12)
at reportTSError (C:\Users\trinitrotoluene\WebstormProjects\ts-node-repro\b\btest\node_modules\ts-node\src\index.ts:591:19)
at getOutput (C:\Users\trinitrotoluene\WebstormProjects\ts-node-repro\b\btest\node_modules\ts-node\src\index.ts:921:36)
at Object.compile (C:\Users\trinitrotoluene\WebstormProjects\ts-node-repro\b\btest\node_modules\ts-node\src\index.ts:1189:32)
at Module.m._compile (C:\Users\trinitrotoluene\WebstormProjects\ts-node-repro\b\btest\node_modules\ts-node\src\index.ts:1295:42)
at Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
at Object.require.extensions.<computed> [as .ts] (C:\Users\trinitrotoluene\WebstormProjects\ts-node-repro\b\btest\node_modules\ts-node\src\index.ts:1298:12)
at Module.load (node:internal/modules/cjs/loader:989:32)
at Function.Module._load (node:internal/modules/cjs/loader:829:14)
at Module.require (node:internal/modules/cjs/loader:1013:19)
Also thank you for the quick responses, I really appreciate it!
I believe this is the same issue as https://github.com/TypeStrong/ts-node/issues/1421, which is due to how TypeScript is unfortunately repeated invoked on files. It doesn't release this is outside the scope of your type checking project and is trying to also type check it.
@cspotcode I think one option might be to default scope
to true
in a future major release, and have the scope automatically set to the root
of tsconfig.json
.
Are we sure that cheerio
is a namespace? Based on the contents of cheerio@1.0.0-rc.10, it looks like cheerio
is a value of type CheerioAPI
, not a namespace nor a type. cheerio
is the default import, right?
https://unpkg.com/browse/cheerio@1.0.0-rc.10/package.json#L28 https://unpkg.com/browse/cheerio@1.0.0-rc.10/lib/index.d.ts#L21 https://unpkg.com/browse/cheerio@1.0.0-rc.10/lib/load.d.ts#L15
Perhaps it would be helpful to locate where the type cheerio.Root
is declared in cheerio's source code.
https://github.com/cheeriojs/cheerio/
I've run into the same issue. My project successfully compiles using tsc
and the tsconfig.json
files I have set up, but when trying to run via ts-node
, I get
TSError: x Unable to compile Typescript:
src/myfile.ts:23:8 - error TS2307: Cannot find module '@myworkspace/mycomponent' or its corresponding type declarations
I'm using:
Hmm, my issue seems to also be related to #897, as I'm working in a monorepo (not lerna, just a yarn PnP monorepo) and the module not being found is being referenced as @myworkspace/mycomponent
, and in package.json
, the dependency entry for it is @myworkspace/mycomponent: workspace:packages/mycomponent
. However, given that ts-node is transpiling on the fly, I would expect it to be able to find the references in tsconfig.json
and build the required dependencies. (Perhaps I expected too much—as I read in another issue, I hadn't fully appreciated the implications of "supporting project references" with respect to ts-node. 😛 )
So on second-thought, maybe these two issues are actually related—and it all comes down to ts-node's support for TS project references?
One way that I had this working in the past is by updating the package.json
so that the main
field points to the typescript entry point, e.g. "main": "./src/index.ts"
, instead of "main": "./lib/index.js"
. Pointing to the typescript file, ts-node works. However, this breaks actual builds of the packages, then, because during a build, the referenced dependencies are expecting to find a TypeScript file, but instead, the transpiled JavaScript should be used.
And now that I think through everything, this makes sense why that change worked. ts-node isn't building the referenced projects, but when the package.json's main
field points to a dependendent package's main entry point TS file, ts-node will happily transpile and everything just works--well, everything except actual builds of the component packages.
See also: #1111 adds the necessary changes for ts-node to understand project references. It also explains what is happening behind the scenes, with TS's internal, monkey-patching of the Host. This monkey-patching teaches the language service that ./lib/index.js
corresponds to ./src/index.ts
If anyone is motivated to finish that pull request, I will be happy to offer guidance, explain what's going on, and list what's missing.
@fourpastmidnight you understand the core issue pretty well. As you said, there are 2 possibilities when @myworkspace/mylib
tries to load @myworkspace/mycomponent
:
@myworkspace/mycomponent
has been pre-compiled and ./lib/index.js
and ./lib/index.d.ts
exist. This may technically work, but is non-ideal: TS will typecheck against .d.ts
and node will resolve to .js
. ts-node will not be executing the source .ts, which is what we probably want.
@myworkspace/mycomponent
has not been compiled yet. #1111 teach ts-node to do the necessary configuration, so that TS understands ./lib/index.js
corresponds to ./src/index.ts
. It understands because the referenced tsconfig has rootDir and outDir, which map between src
and lib
. This is halfway there: the typechecker understands to typecheck against index.ts
, but node does not understand which file to load. Node will attempt to require ./lib/index.js
which does not exist. We need to teach node to do the same mappings that TypeScript does. I talk about this in #1111 under "Missing is a runtime resolver"
I'm fairly new to all of this, having been thrown into a last-minute project that was a perfect use-case for React. I've learned a lot in the last 3 months, but still not 100% on this ecosystem 😉 I had a look at #1111, but I'm unable to quickly make heads or tails of it. Glad to see, however, that I do understand the core issue even if I'm not quite sure (yet) what it would take to bring #1111 to completion.
I wound up here again, reading my 14-day old self and your replies because I was once again trying to get ts-node to work with my (the same) project.... LOL. Anyway, it would be super sweet to have #1111 done and implemented. So I guess I should now try to see if I can't figure out what the heck that's all doing! LOL. No promises, I'm busy, but I'd really like to have a quick "F5" experience.
@fourpastmidnight yeah, it's like everything in open-source. Someone's got to do it, but the benefits are huge once it gets done.
If/when you start working on this, please do not hesitate to create draft pull requests, ask questions, create issues, whatever you need to feel productive. The PR and issue trackers exist to "get things done" and I'm a big proponent of pushing WIP, chatting, whatever fits your workflow.
I landed here after trying to setup an experimental project with yarn workspaces, typescript project references, snowpack for the client side and node --loader ts-node/esm
for the server side. I'm trying to feed both snowpack and ts-node/esm the raw .ts files. This works until they cross a package border (across the monorepo's own packages).
I give snowpack the packages/client/src/index.ts
file to start with. Any file it imports in it's own package snowpack will find the .ts file. However when it does import x from "@myapp/shared"
snowpack will find the symlinked package in node_modules, lookup the package.json, lookup the main
field and find lib/index.js
. Then it will continue to build it's dependency chain using .js files instead. So when a .ts file is changed in the shared package snowpack does not have it in it's chain and nothing happens. To fix this it is possible to invent a new field instead of main
, let's say tsMain
and set it to src/index.ts
. Then in snowpack config you can set packageLookupFields: ["tsMain", "main"]
and snowpack will prefer tsMain
and it will build a chain of only ts files across the package borders.
Now for node --loader ts-node/esm
that does not work of course since there is no equivalent of snowpack's packageLookupFields
config. From what I understand here ts-node is trying to solve this by working in the same way as the language server in vscode. Looking up in tsconfig.json what is the input and output dirs (usually lib
and src
) and rewriting the main
field to map to it's corresponding input file (from the compiler option rootDir).
@cspotcode Is this a correct understanding of the situation?
I think it would be great if the logic to do the re-mapping of lib/index.js
to src/index.ts
could be externalized from ts-node but I don't think it really belongs in tsconfig-paths
either since this is not related to the paths
field in tconfig.json? If it is externalized perhaps tools like snowpack can leverage this logic too instead of having the hack with tsMain
field I described above.
If I can help with this I will try subject to time constraints (still haven't got those 36h days I wished for Christmas for the last 20 years :-)).
EDIT: Here is an example repo for what i described above, and this note is about the limitation of module resolution.
+1 this does not work in NX workspaces when I tried to run a node CLI tool that is using some other packages withing the monorepo which are configured via tsconfig paths property in NX.
Would be great to have an option to somehow make it resolve those aliases, as for now it cannot find those workspace packages.
I was able to use tsx
instead for now to execute my cli project locally which resolves all tsconfig paths out of the box.
tsx
is the clear winner! Thx @gund
Expected Behavior
I would expect code that doesn't error when trying to compile it with
tsc
to compile when run throughts-node
.Actual Behavior
I get a TSError warning me about missing dependencies (the README linked below) when ts-node tries to load a referenced project.
Reproduction
I've created a minimal reproduction repo for my scenario here with the behaviour/stack trace and command to reproduce.
Specifications