Skip to content

Declaration emit can't utilize exports map information and ends up reporting "this is likely not portable"Β #56107

Closed
@Andarist

Description

@Andarist

πŸ”Ž Search Terms

declaration emit nodenext exports map package.json inferred type annotation necessary

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried

⏯ Playground Link

No response

πŸ’» Code

// @strict: true
// @declaration: true
// @module: nodenext
// @noImplicitReferences: true

// @filename: node_modules/effect/dist/declarations/src/Data.d.ts
import type * as Types from "./Types.js";
import type * as Equal from "./Equal.js";

export type Data<A extends Readonly<Record<string, any>> | ReadonlyArray<any>> =
  Readonly<A> & Equal.Equal;

export declare const TaggedClass: <Key extends string>(
  tag: Key,
) => new <A extends Record<string, any>>(
  args: Types.Equals<Omit<A, keyof Equal.Equal>, {}> extends true
    ? void
    : Omit<A, keyof Equal.Equal>,
) => Data<
  A & {
    _tag: Key;
  }
>;

// @filename: node_modules/effect/dist/declarations/src/Equal.d.ts
import * as Hash from "./Hash.js";

export declare const symbol: unique symbol;

export interface Equal extends Hash.Hash {
  [symbol](that: Equal): boolean;
}

// @filename: node_modules/effect/dist/declarations/src/Hash.d.ts
export declare const symbol: unique symbol;

export interface Hash {
  [symbol](): number;
}

// @filename: node_modules/effect/dist/declarations/src/Types.d.ts
export type Equals<X, Y> = (<T>() => T extends X ? 1 : 2) extends <
  T,
>() => T extends Y ? 1 : 2
  ? true
  : false;

// @filename: node_modules/effect/dist/declarations/src/index.d.ts
export * as Data from "./Data.js";

// @filename: node_modules/effect/dist/effect.cjs.d.ts
export * from "./declarations/src/index";

// @filename: node_modules/effect/Equal/dist/effect-Equal.cjs.d.ts
export * from "../../dist/declarations/src/Equal";

// @filename: node_modules/effect/Types/dist/effect-Types.cjs.d.ts
export * from "../../dist/declarations/src/Types";

// @filename: node_modules/effect/package.json
{
  "name": "effect",
  "exports": {
    ".": "./dist/effect.cjs.js",
    "./Equal": "./Equal/dist/effect-Equal.cjs.js",
    "./Types": "./Types/dist/effect-Types.cjs.js"
  }
}

// @filename: src/index.ts
import { Data } from "effect";
export class Foo extends Data.TaggedClass("Foo")<{}> {}

πŸ™ Actual behavior

==== src/index.ts (2 errors) ====
    import { Data } from "effect";
    export class Foo extends Data.TaggedClass("Foo")<{}> {}
                 ~~~
!!! error TS2742: The inferred type of 'Foo' cannot be named without a reference to '../node_modules/effect/dist/declarations/src/Equal'. This is likely not portable. A type annotation is necessary.
                 ~~~
!!! error TS2742: The inferred type of 'Foo' cannot be named without a reference to '../node_modules/effect/dist/declarations/src/Types'. This is likely not portable. A type annotation is necessary.

πŸ™‚ Expected behavior

//// [index.d.ts]
import { Data } from "effect";
declare const Foo_base: new <A extends Record<string, any>>(args: import("effect/Types").Equals<Omit<A, keyof import("effect/Equal").Equal>, {}> extends true ? void : Omit<A, keyof import("effect/Equal").Equal>) => Data.Data<A & {
    _tag: "Foo";
}>;
export declare class Foo extends Foo_base<{}> {
}
export {};

Additional information about the issue

I think that it would be best if the listed exports entries (especially the ones not relying on wildcards but the wildcard support would also be nice) could be automatically loaded by the compiler at some stage of the declaration emit.

In this case, this would allow the compiler to discover effect/Types and effect/Equal and getAlternativeContainingModules could return them.

cc @andrewbranch as package.json#exports is your turf πŸ˜‰

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions