denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
97.72k stars 5.38k forks source link

Cannot import when package composed of index.d.ts file #26767

Open togakangaroo opened 1 week ago

togakangaroo commented 1 week ago
deno 2.0.3 (stable, release, x86_64-unknown-linux-gnu)
v8 12.9.202.13-rusty
typescript 5.6.2

I first tried asking in Discord but got no bites so asking here.

Basically, when a package contains an index.d.ts file such as with type-fest, I can't figure out the right way to import it in Deno nor co I understand what the intent is for how this should work.

Broader context is largely a question about node compatibility as what I really want is to run my existing large node/typescript project in Deno so that I can get good jupyter integration. I've managed to figure things out to where they mostly work but am running into issues where my existing code uses the npm type-fest package to provide advanced typescript types.

So as an example, I have the following import in my code

import { LiteralUnion } from 'type-fest'

I can't for the life of me get this to work.

But lets set the issue of node-compatibility aside as I'm not sure how relevant it is here. I get the following in just the straight-up repl as well

gmauer:/tmp$ /home/gmauer/.deno/bin/deno repl
Deno 2.0.3
exit using ctrl+d, ctrl+c, or close()
> 
import { LiteralUnion } from 'npm:type-fest'
> Download ⣯ [00:05]
 - npm:type-fest
Download ⣽ [00:06] 1/2
 - npm:type-fest/-/type-fest-4.26.1.tgz

Uncaught TypeError: [ERR_MODULE_NOT_FOUND] Cannot find module 'file:///home/gmauer/.cache/deno/npm/registry.npmjs.org/type-fest/4.26.1/index.js' imported from 'file:///tmp/$deno$repl.ts'
    at async <anonymous>:1:47

This seems to be because whats inside of there is index.d.ts not index.js Interestingly, I can't do npm:type-fest/index.d.ts either as it seems to error out at the 8th line which begins with export type.

I'm honestly not sure if this is a bug, an expected behavior, a bug in type-fest or what. It doesn't seem like a type-fest issue as they don't seem to be doing anything wrong here, this is all perfectly normal typescript and idioms. I also know they've had some issues with deno in the past but they were resolved years ago

nathanwhit commented 1 week ago

The issue is that when you

import { LiteralUnion } from 'npm:type-fest'

we expect there to be an actual runtime value there, and so we look for a file with actual code in it (i.e. not a declaration file).

What you want is a type-only import

import type { LiteralUnion } from 'npm:type-fest'

which should work for you.

(the examples / docs for type-fest use type-only imports as well)


I'm not quite sure either if this is expected behavior or not, it's definitely subtle and the error message is not helpful. At a minimum we should provide some better diagnostics here, but I'll see what others think.

bartlomieju commented 1 week ago

FYI I checked this in Node.js and the result is pretty much the same:

node main.mjs
node:internal/modules/esm/resolve:204
  const resolvedOption = FSLegacyMainResolve(pkgPath, packageConfig.main, baseStringified);
                         ^

Error: Cannot find package '/Users/ib/dev/scratch_type_fest/node_modules/type-fest/index.js' imported from /Users/ib/dev/scratch_type_fest/main.mjs
    at legacyMainResolve (node:internal/modules/esm/resolve:204:26)
    at packageResolve (node:internal/modules/esm/resolve:846:14)
    at moduleResolve (node:internal/modules/esm/resolve:926:18)
    at defaultResolve (node:internal/modules/esm/resolve:1056:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:650:12)
    at #cachedDefaultResolve (node:internal/modules/esm/loader:599:25)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:582:38)
    at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:241:38)
    at ModuleJob._link (node:internal/modules/esm/module_job:132:49) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Node.js v23.1.0