Skip to content

Incorrect d.ts for js project when module.exports an array #49397

Closed

Description

Bug Report

🔎 Search Terms

module, module.exports, module exports, array, js, d.ts, declaration file

🕗 Version & Regression Information

Affected 3.7.5 and 4.7.2 and probably all of between them, did not test before 3.7.5.

This is the behavior in every version I tried, and I reviewed the FAQ for entries about declaration

⏯ Playground Link

https://tsplay.dev/Wy4kJm

💻 Code

// Produces wrong d.ts
module.exports = [{ name: 'other', displayName: 'Other', defaultEnabled: true }];
// Produces right d.ts
const r = [{ name: 'other', displayName: 'Other', defaultEnabled: true }];
module.exports = r;

🙁 Actual behavior

Produces wrong declaration file and make a copy of all array methods in place.

🙂 Expected behavior

Produces correct declaration file using T[] syntax.

Activity

  1. fatcerberus commented on Jun 6, 2022

    @fatcerberus

    For anyone else reading this issue (since it wasn't clear to me what was wrong from the OP), this is what was meant by "wrong d.ts":

    declare const _exports: {
        [n: number]: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        };
        length: number;
        toString(): string;
        toLocaleString(): string;
        pop(): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        };
        push(...items: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]): number;
        concat(...items: ConcatArray<{
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }>[]): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[];
        concat(...items: ({
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        } | ConcatArray<{
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }>)[]): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[];
        join(separator?: string): string;
        reverse(): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[];
        shift(): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        };
        slice(start?: number, end?: number): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[];
        sort(compareFn?: (a: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, b: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }) => number): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[];
        splice(start: number, deleteCount?: number): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[];
        splice(start: number, deleteCount: number, ...items: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[];
        unshift(...items: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]): number;
        indexOf(searchElement: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, fromIndex?: number): number;
        lastIndexOf(searchElement: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, fromIndex?: number): number;
        every<S extends {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }>(predicate: (value: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, index: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => value is S, thisArg?: any): this is S[];
        every(predicate: (value: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, index: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => unknown, thisArg?: any): boolean;
        some(predicate: (value: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, index: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => unknown, thisArg?: any): boolean;
        forEach(callbackfn: (value: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, index: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => void, thisArg?: any): void;
        map<U>(callbackfn: (value: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, index: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => U, thisArg?: any): U[];
        filter<S_1 extends {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }>(predicate: (value: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, index: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => value is S_1, thisArg?: any): S_1[];
        filter(predicate: (value: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, index: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => unknown, thisArg?: any): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[];
        reduce(callbackfn: (previousValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, currentValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, currentIndex: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        };
        reduce(callbackfn: (previousValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, currentValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, currentIndex: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, initialValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        };
        reduce<U_1>(callbackfn: (previousValue: U_1, currentValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, currentIndex: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => U_1, initialValue: U_1): U_1;
        reduceRight(callbackfn: (previousValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, currentValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, currentIndex: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        };
        reduceRight(callbackfn: (previousValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, currentValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, currentIndex: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, initialValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        };
        reduceRight<U_2>(callbackfn: (previousValue: U_2, currentValue: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, currentIndex: number, array: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => U_2, initialValue: U_2): U_2;
        find<S_2 extends {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }>(predicate: (this: void, value: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, index: number, obj: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => value is S_2, thisArg?: any): S_2;
        find(predicate: (value: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, index: number, obj: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => unknown, thisArg?: any): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        };
        findIndex(predicate: (value: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, index: number, obj: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[]) => unknown, thisArg?: any): number;
        fill(value: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, start?: number, end?: number): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[];
        copyWithin(target: number, start: number, end?: number): {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }[];
        entries(): IterableIterator<[number, {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }]>;
        keys(): IterableIterator<number>;
        values(): IterableIterator<{
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }>;
        includes(searchElement: {
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }, fromIndex?: number): boolean;
        [Symbol.iterator](): IterableIterator<{
            name: string;
            displayName: string;
            defaultEnabled: boolean;
        }>;
        [Symbol.unscopables](): {
            copyWithin: boolean;
            entries: boolean;
            fill: boolean;
            find: boolean;
            findIndex: boolean;
            keys: boolean;
            values: boolean;
        };
    };
    export = _exports;

    That's, um... very, very bad! 😱

  2. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScriptDomain: Declaration EmitThe issue relates to the emission of d.ts filesFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions