Skip to content

Declaration: JSDoc of local class expression disappears when placed in different files #27295

Description

@winhillsen

TypeScript Version: typescript@3.1.0-dev.20180922

Search Terms:
JSDoc disappears. Local class. Comment disappears. Definition file. d.ts.

Code

This is a mix-in pattern that otherwise works well: the mixin function locally derives from the supplied base class. The issue is that when the mixin function lives in a different file from the class that extends it, documentation to the local class expression disappears.

// index.ts
import { Base } from "./base";
export { Base } from './base';
export { Mixed } from './mixed';

function localMix<T extends new (...args: any[]) => any>(Base: T) {
  return class Mixed extends Base {
    /**
     * I am bar
     */
    bar = 1;
  };
}

export class LocalMixed extends localMix(Base) {
  /**
   * I am baz
   */
  baz = 1;
}
// base.ts
export class Base
{
    /**
     * I am foo
     */
    foo = 1;
}
// mixed.ts
import { Base } from './base';
import { mix } from './mix';
export class Mixed extends mix(Base) {
        /**
         * I am baz
         */
        baz = 1;
};
// mix.ts
export function mix<T extends new (...args: any[]) => any>( Base: T )
{
    return class Mixed extends Base
    {
        /**
         * I am bar
         */
        bar = 1;
    }
}

Expected behavior:

Both Mixed and LocalMixed should have identical documentation.

Actual behavior:

Mixed misses documentation on bar. The generated Mixed_base does not retain the documentation of bar from the local class.

// mixed.d.ts
import { Base } from "./base";
declare const Mixed_base: {
    new (...args: any[]): {
        [x: string]: any;
        bar: number;
    };
} & typeof Base;
export declare class Mixed extends Mixed_base {
    /**
     * I am baz
     */
    baz: number;
}
export {};

In contrast, looking into the generated index.d.ts shows that LocalMixed is properly documented. (Base is also properly documented, not shown here)

// index.d.ts
import { Base } from "./base";
export { Base } from "./base";
export { Mixed } from "./mixed";
declare const LocalMixed_base: {
    new (...args: any[]): {
        [x: string]: any;
        /**
         * I am bar
         */
        bar: number;
    };
} & typeof Base;
export declare class LocalMixed extends LocalMixed_base {
    /**
     * I am baz
     */
    baz: number;
}

Other observations

Interestingly, if I change the order of extension such that the mixin is applied after the extension:

// mixed.ts
import { Base } from "./base";
import { mix } from "./mix";
export const Mixed = mix(
  class Mixed extends Base {
    /**
     * I am baz
     */
    baz = 1;
  }
);

Now I also lose the documentation of Base as well as of the local class expression.

// mixed.d.ts
export declare const Mixed: {
    new (...args: any[]): {
        [x: string]: any;
        bar: number;
    };
} & {
    new (): {
        /**
         * I am baz
         */
        baz: number;
        foo: number;
    };
};

Playground Link: Not relevant because this involves files in different places and involves d.ts generation.

Related Issues: Couldn't really find anything, but this seemed quite a specific set of scenarios that it was hard to search to begin with.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions