Skip to content

Project doesn't resolve ESM only exports reported by getExportedDeclarations #1667

@jason-ha

Description

@jason-ha

Describe the bug

Version: 27.0.2

DocumentRegistry in @ts-morph/common passes compilationSettings.target (a bare ScriptTarget) to ts.createLanguageServiceSourceFile instead of a CreateSourceFileOptions with impliedNodeFormat. This means source files never know their module format.

To Reproduce

node_modules/packageA/package.json:

{
   "name": "packageA",
   "exports": { ".": { "import": "./lib/index.js" } }
}

node_modules/packageA/lib/index.d.ts:

export type Foo = "Foo";

package.json:

{
   "type": "module"
}

tsconfig.json:

{ "compilerOptions": { "module": "Node16" } }

test.ts:

export type { Foo } from "packageA";

usage:

import { Project } from "ts-morph";

const project = new Project({
      tsConfigFilePath: "./tsconfig.json",
      skipAddingFilesFromTsConfig: true,
    });
const sourceFile = project.addSourceFileAtPath("test.ts");

const exports = sourceFile.getExportedDeclarations();

assert(exports.get("Foo")!.length > 0);

Workaround

const pkgJson = JSON.parse(fs.readFileSync("./package.json", "utf-8"));
const isESM = pkgJson.type === "module";
const project = new Project({
      tsConfigFilePath: "./tsconfig.json",
      skipAddingFilesFromTsConfig: true,
      compilerOptions: {
        customConditions: [isESM ? "import" : "require"],
      },
    });

Expected behavior

ts-morph should call ts.getImpliedNodeFormatForFile() and pass the result via CreateSourceFileOptions, matching tsc behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions