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

When relatively importing a .d.ts file in a declaration file, TypeScript loads a .ts file instead #58353

Open
lucacasonato opened this issue Apr 29, 2024 · 8 comments Β· May be fixed by #58700
Open
Assignees
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status.

Comments

@lucacasonato
Copy link

lucacasonato commented Apr 29, 2024

πŸ”Ž Search Terms

  • module resolution
  • probing

πŸ•— Version & Regression Information

TypeScript 5.4.3

⏯ Playground Link

No response

πŸ’» Code

// package.json
{
  "name": "test4",
  "dependencies": {
    "@std/fs": "npm:@jsr/std__fs@^0.224.0"
  }
}
// package-lock.json
{
  "name": "test4",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "dependencies": {
        "@std/fs": "npm:@jsr/std__fs@^0.224.0"
      }
    },
    "node_modules/@jsr/std__assert": {
      "version": "0.224.0",
      "resolved": "https://npm.jsr.io/~/8/@jsr/std__assert/0.224.0.tgz",
      "integrity": "sha512-2JTYGKyQ9Rb9NEalTJIN3LZ5NaDuoOpHesqP1+5sjjTXVYkzLgDoykjaFwWBJ+70YIg2Tctkj1xoaG0ga7tzsg==",
      "dependencies": {
        "@jsr/std__fmt": "^0.224.0",
        "@jsr/std__internal": "^0.224.0"
      }
    },
    "node_modules/@jsr/std__fmt": {
      "version": "0.224.0",
      "resolved": "https://npm.jsr.io/~/8/@jsr/std__fmt/0.224.0.tgz",
      "integrity": "sha512-rj0m00LslTlQJyXmkWe114v9aSbK81B33VcgIrYaaRuE7DTiFe6cebkNGQdAPQemLC4vRqiQMOZ247GdFFhk4g=="
    },
    "node_modules/@jsr/std__internal": {
      "version": "0.224.0",
      "resolved": "https://npm.jsr.io/~/8/@jsr/std__internal/0.224.0.tgz",
      "integrity": "sha512-pinRPGlSqi0qgFGDs1LUJ8vIe0p1jh6SIt2b02266a4OIO7RSTQiZNd21PV9UIFuJbaNTsskhGzqlN2ePvPU0Q==",
      "dependencies": {
        "@jsr/std__fmt": "^0.224.0"
      }
    },
    "node_modules/@jsr/std__path": {
      "version": "0.224.0",
      "resolved": "https://npm.jsr.io/~/8/@jsr/std__path/0.224.0.tgz",
      "integrity": "sha512-E8Nyv8dox8vR5wbA4FS7wMlSctZ6L1CVwshMrNLgFUqcCOE3VCvjKokgXs43sJEcq3w8aIY62j/mDxeFIOvwvA==",
      "dependencies": {
        "@jsr/std__assert": "^0.224.0"
      }
    },
    "node_modules/@std/fs": {
      "name": "@jsr/std__fs",
      "version": "0.224.0",
      "resolved": "https://npm.jsr.io/~/8/@jsr/std__fs/0.224.0.tgz",
      "integrity": "sha512-z7dnRgqDlgqnm9P0oJYiur0uFmKoQ5zOujbm5X+KwbJb6cnmpw7PrzMroq3PWy0kNOkGMLb0AU3IlENa+cVmTA==",
      "dependencies": {
        "@jsr/std__assert": "^0.224.0",
        "@jsr/std__path": "^0.224.0"
      }
    }
  }
}
$ npm i
// tsconfig.json
{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "bundler"
  }
}
// index.ts
import { walk } from "@std/fs/walk";

πŸ™ Actual behavior

$ tsc --explainFiles
node_modules/@std/fs/_create_walk_entry.ts:12:36 - error TS2503: Cannot find namespace 'Deno'.

12 export interface WalkEntry extends Deno.DirEntry {
                                      ~~~~

node_modules/@std/fs/_create_walk_entry.ts:22:16 - error TS2304: Cannot find name 'Deno'.

22   const info = Deno.statSync(path);
                  ~~~~

node_modules/@std/fs/_create_walk_entry.ts:25:5 - error TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'WalkEntry'.

25     name,
       ~~~~

node_modules/@std/fs/_create_walk_entry.ts:33:60 - error TS2705: An async function or method in ES5/ES3 requires the 'Promise' constructor.  Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your '--lib' option.

33 export async function createWalkEntry(path: string | URL): Promise<WalkEntry> {
                                                              ~~~~~~~~~~~~~~~~~~

node_modules/@std/fs/_create_walk_entry.ts:37:22 - error TS2304: Cannot find name 'Deno'.

37   const info = await Deno.stat(path);
                        ~~~~

node_modules/@std/fs/_create_walk_entry.ts:40:5 - error TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'WalkEntry'.

40     name,
       ~~~~

node_modules/@std/fs/walk.d.ts:1:32 - error TS2846: A declaration file cannot be imported without 'import type'. Did you mean to import an implementation file './_create_walk_entry.js' instead?

1 import { type WalkEntry } from "./_create_walk_entry.d.ts";
                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@std/fs/walk.d.ts:99:73 - error TS2583: Cannot find name 'AsyncIterableIterator'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2018' or later.

99  */ export declare function walk(root: string | URL, {}?: WalkOptions): AsyncIterableIterator<WalkEntry>;
                                                                           ~~~~~~~~~~~~~~~~~~~~~

node_modules/@std/fs/walk.d.ts:100:130 - error TS2304: Cannot find name 'IterableIterator'.

100 /** Same as {@linkcode walk} but uses synchronous ops */ export declare function walkSync(root: string | URL, {}?: WalkOptions): IterableIterator<WalkEntry>;
                                                                                                                                     ~~~~~~~~~~~~~~~~

../../../../.config/yarn/global/node_modules/typescript/lib/lib.d.ts
  Default library for target 'es5'
../../../../.config/yarn/global/node_modules/typescript/lib/lib.es5.d.ts
  Library referenced via 'es5' from file '../../../../.config/yarn/global/node_modules/typescript/lib/lib.d.ts'
../../../../.config/yarn/global/node_modules/typescript/lib/lib.dom.d.ts
  Library referenced via 'dom' from file '../../../../.config/yarn/global/node_modules/typescript/lib/lib.d.ts'
../../../../.config/yarn/global/node_modules/typescript/lib/lib.webworker.importscripts.d.ts
  Library referenced via 'webworker.importscripts' from file '../../../../.config/yarn/global/node_modules/typescript/lib/lib.d.ts'
../../../../.config/yarn/global/node_modules/typescript/lib/lib.scripthost.d.ts
  Library referenced via 'scripthost' from file '../../../../.config/yarn/global/node_modules/typescript/lib/lib.d.ts'
../../../../.config/yarn/global/node_modules/typescript/lib/lib.decorators.d.ts
  Library referenced via 'decorators' from file '../../../../.config/yarn/global/node_modules/typescript/lib/lib.es5.d.ts'
../../../../.config/yarn/global/node_modules/typescript/lib/lib.decorators.legacy.d.ts
  Library referenced via 'decorators.legacy' from file '../../../../.config/yarn/global/node_modules/typescript/lib/lib.es5.d.ts'
node_modules/@jsr/std__path/basename.d.ts
  Imported via "@jsr/std__path/basename" from file 'node_modules/@std/fs/_create_walk_entry.ts' with packageId '@jsr/std__path/basename.d.ts@0.224.0'
node_modules/@jsr/std__path/normalize.d.ts
  Imported via "@jsr/std__path/normalize" from file 'node_modules/@std/fs/_create_walk_entry.ts' with packageId '@jsr/std__path/normalize.d.ts@0.224.0'
node_modules/@jsr/std__path/from_file_url.d.ts
  Imported via "@jsr/std__path/from-file-url" from file 'node_modules/@std/fs/_to_path_string.ts' with packageId '@jsr/std__path/from_file_url.d.ts@0.224.0'
node_modules/@std/fs/_to_path_string.ts
  Imported via "./_to_path_string.js" from file 'node_modules/@std/fs/_create_walk_entry.ts' with packageId '@jsr/std__fs/_to_path_string.ts@0.224.0'
node_modules/@std/fs/_create_walk_entry.ts
  Imported via "./_create_walk_entry.d.ts" from file 'node_modules/@std/fs/walk.d.ts' with packageId '@jsr/std__fs/_create_walk_entry.ts@0.224.0'
node_modules/@std/fs/walk.d.ts
  Imported via "@std/fs/walk" from file 'index.ts' with packageId '@jsr/std__fs/walk.d.ts@0.224.0'
index.ts
  Matched by default include pattern '**/*'

Found 9 errors in 2 files.

Errors  Files
     6  node_modules/@std/fs/_create_walk_entry.ts:12
     3  node_modules/@std/fs/walk.d.ts:1

From the walk.d.ts file (referenced specified in package.json "types" conditional export), a type is imported from ./_create_walk_entry.d.ts. TypeScript however does not load ./_create_walk_entry.d.ts, but instead loads ./_create_walk_entry.ts (and then tries to check it) even though ./_create_walk_entry.d.ts exists. Why?

The .ts files are included in the published package to enable "Go to source definition" for users. Is it really necessary to place all generated files into a separate directory?

πŸ™‚ Expected behavior

No .ts file to be loaded, because all specifiers (both in conditional exports, and in declaration files) reference .d.ts files.

This is especially the case because when declaration: true is specified, TypeScript will by default place .js and .d.ts directly next to the .ts code. If you publish this to npm, it will not work.

Additional information about the issue

No response

@MartinJohns
Copy link
Contributor

The .ts files are included in the published package to enable "Go to source definition" for users. Is it really necessary to place all generated files into a separate directory?

Yes. A .ts is always preferred over the .d.ts. The declaration file is considered a build artifact of the TypeScript file.

See also #56412 (comment) and #15272.

@fatcerberus
Copy link

Also worth noting is that "Go to source definition" only works at all because the TS language service prefers to load the .ts over the .d.ts

@andrewbranch
Copy link
Member

This is currently expected behavior, but I do think we should explore changing it. This happens to avoid loading your own output files as part of your input files, but it doesn’t make a lot of sense to do for files that you didn’t emit, e.g. declaration files in node_modules.

@RyanCavanaugh
Copy link
Member

I'm confused how this project even builds. The inclusion of this .ts file should have been a rootDir and/or composite violation, and we should be trying to emit a .d.ts file for it.

Can we get a sample repo?

@sheetalkamat
Copy link
Member

If file is imported from node_modules its not considered for "rootDir" and "composite" calculations as it wont be emitted

@lucacasonato
Copy link
Author

I'll set up a reproduction repo tomorrow

@lucacasonato
Copy link
Author

Made a small reproduction, instructions are in the README: https://github.com/lucacasonato/typescript-issue-58353

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label May 2, 2024
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 5.6.0 milestone May 2, 2024
@lucacasonato
Copy link
Author

Our workaround for this was emitting both the .js and .d.ts files into a separate directory, but this has other issues (namely import.meta.url is now wrong for users, e.g jsr-io/jsr#477).

We'll try again here, by only emitting .d.ts files into a subdirectory, and keeping the .js files next to the .ts files - I think this will work, because we can already rewrite specifiers in the .d.ts files, but it'll be weird.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
7 participants