Skip to content

TypeScript Function Overload Type Loss #1188

@jtmenchaca

Description

@jtmenchaca

Hello! First just want to say thanks for the great functionality. Ran into a types issue with object literals containing functions after using the package to install one of my JSR packages (@tidy-ts/dataframe). Had Claude help me provide a little write up:

Issue Summary: TypeScript Function Overload Type Loss in JSR npm Distribution

Problem Description

When a JSR package exports object literals containing imported functions, the TypeScript compilation process for npm distribution loses function signature information, resulting in all function properties being typed as any instead of preserving their original overloaded signatures.

Reproduction Steps

  1. Source TypeScript (works correctly in Deno):

    // stats.ts
    import { sum } from "./sum.ts";  // sum has multiple overloads
    
    export const stats = {
      sum,  // Should preserve typeof sum with all overloads
    };
  2. Expected behavior (Deno direct import):

    const stats: {
      sum: {
        (value: number): number;
        (values: CleanNumberArray): number;
        (values: NumbersWithNullable, remove_na: true): number;
        // ... more overloads
      };
    }
  3. Actual behavior (JSR npm distribution):

    const stats: {
      readonly sum: any;  // Type information lost
    }

Root Cause Analysis

The issue occurs in JSR's TypeScript-to-npm compilation pipeline:

  1. Source compilation: JSR compiles TypeScript to JavaScript + .d.ts files
  2. Type inference limitation: When TypeScript generates .d.ts files for object literals with imported functions, it creates:
    import { sum } from "./sum.js";  // Value import, not type import
    export declare const stats: {
      readonly sum;  // No explicit type - becomes `any`
    };
  3. Missing type preservation: The generated .d.ts doesn't preserve the typeof sum relationship that would maintain function signatures

Technical Details

  • Works in Deno: Direct TypeScript import preserves all type information
  • Fails in npm: Compiled .d.ts files lose function signature details
  • Affected pattern: Object literals with imported function values
  • Scope: Any exported object containing functions with overloads

Workaround Solution

Add explicit type annotations using typeof to preserve function signatures:

export const stats: {
  readonly sum: typeof sum;  // Preserves all overloads
  readonly mean: typeof mean;
  // ...
} = {
  sum,
  mean,
  // ...
};

Suggested JSR Improvements

  1. Enhanced type preservation: Improve the TypeScript compilation process to better preserve typeof relationships in generated .d.ts files
  2. Type import handling: Consider using type-only imports in generated .d.ts files where appropriate
  3. Documentation: Add guidance for package authors about this limitation and the workaround

I imagine this might affect any JSR package that exports objects containing functions with overloads. Haven't checked that out myself though. Thanks again for the great work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Needs Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions