question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItΒ collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Declaration emit reveals paths within dependency that were not referred to in the source file

See original GitHub issue

Context:

  • Generating declaration files

Declaration emit reveals paths within dependency that were not referred to in the source file:

export declare const instance: import("dependency/internal-types").TheInterface;

This is a problem because changing paths within a dependency can break a dependent package.

TypeScript Version: 3.9.0-dev.20200212

Search Terms:

Code

node_modules/@types/dependency/entrypoint.d.ts

import { TheInterface } from "./internal-types";
export { TheInterface };
export declare function getInstance(): TheInterface;

node_modules/@types/dependency/internal-types.d.ts

export interface TheInterface {}

node_modules/@types/dependency/index.d.ts

// empty - doesn't matter for this example

example.ts

import { getInstance } from "dependency/entrypoint";
export const instance = getInstance();

src/app/tsconfig.json

{
    "compilerOptions": {
        "declaration": true,
    }
}

Expected behavior:

example.d.ts

export declare const instance: import("dependency/entrypoint").TheInterface;

Actual behavior:

example.d.ts

export declare const instance: import("dependency/internal-types").TheInterface;

It seems that part of the solution could involve having the compiler avoid using relative paths in types (import("<relativepath>").<typename>) if the relativepath is outside the project.

Repro Repo: https://github.com/mheiber/repro-rel-import-inlining

Related Issues:

  • Declaration emit should not inline type definitions - #37151
  • Proposal: Bundling TS module type definitions - #4433

Issue written with the help of: @rricard, @robpalme and @mkubilayk

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:4
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

5reactions
remcohaszingcommented, Sep 7, 2022

This has gotten worse with the introduction of "moduleResolution": "node16". Paths are now rewritten to relative paths inside node_modules. (import('mdast-util-from-markdown') yields import("../../../node_modules/mdast-util-from-markdown/lib/index.js"))

https://github.com/remarkjs/remark/issues/1039#issuecomment-1239253894

3reactions
rricardcommented, Apr 23, 2020

When writing up that issue we also found out a pretty interesting effect.

If you were to move the internal-types.d.ts into a sub-directory in the dependency and have entrypoint load it:

node_modules/@types/dependency/entrypoint.d.ts

import { TheInterface } from "./int/internal-types";
export { TheInterface };
export declare function getInstance(): TheInterface;

We do get the wanted declaration output:

example.d.ts

export declare const instance: import("dependency/entrypoint").TheInterface;

This is great because that means that TypeScript has a notion of some files are meant to be imported and others do not.

At the moment it seems like everything in the root of the dependency is considered importable externally while subdirectories are not. Actually the rule seems to be, whoever is the least deep gets it:

checker.ts:5014

                    function sortByBestName(a: number, b: number) {
                        const specifierA = parentSpecifiers[a];
                        const specifierB = parentSpecifiers[b];
                        if (specifierA && specifierB) {
                            const isBRelative = pathIsRelative(specifierB);
                            if (pathIsRelative(specifierA) === isBRelative) {
                                // Both relative or both non-relative, sort by number of parts
                                return moduleSpecifiers.countPathComponents(specifierA) - moduleSpecifiers.countPathComponents(specifierB);
                            }
                            if (isBRelative) {
                                // A is non-relative, B is relative: prefer A
                                return -1;
                            }
                            // A is relative, B is non-relative: prefer B
                            return 1;
                        }
                        return 0;
                    }

#27340 / 7a71887c23a110009bc974f626245f03066e6926 by @weswigham

Is that behavior intentional, in which case we can use it as a workaround, or is this arbitrary behavior that can change?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Do I have to reference TypeScript definition in every file?
One way to do this is by making sure all required declaration files and TypeScript source files are passed to the compiler as...
Read more >
Authoring Tasks - Gradle User Manual
Dependencies between projects should be declared as dependencies. You can access tasks from any project using the task's path using the tasks.
Read more >
Documentation - Project References - TypeScript
Project references are a new feature in TypeScript 3.0 that allow you to structure your TypeScript programs into smaller pieces.
Read more >
Processes β€” Nextflow 22.10.4 documentation
The path qualifier allows you to provide input files to the process execution context. Nextflow will stage the files into the process execution...
Read more >
Swift Package Manager
The Swift Package Manager will emit an error if a dependency is not ... Each target contains a set of source files that...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found