镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

JS declarations for an export assigned class expression can conflict with local names #33626

Description

Per this comment on the PR, the JS declaration emitter currently has a known issue where an export assigned class expression with a name can cause a conflict with another named declaration in the file and produce an invalid declaration file.

So, for example, this:

class A { member = new Q(); };
class Q { x = 12 };
module.exports = class Q { x = new A(); }

currently emits along the lines of

declare class A { member: Q; };
declare class Q { x: number };
declare class Q { x: A; }
exports = Q;

(because it reused the anonymous class's name for the hoisted class declaration) which isn't quite right.

Activity

  1. Bnaya commented on Oct 11, 2019

    @Bnaya

    I have a similar issue with esm default export:
    code:

    import React from "react";
    /**
     * @type {React.FunctionComponent}
     */
    const TabbedShowLayout = ({
        classes: classesOverride,
        className,
        version,
    }) => {
        return (
            <div className={className} key={version}>
                {className}
            </div>
        );
    };
    
    
    TabbedShowLayout.defaultProps = {
        tabs: "default value"
    };
    
    export default TabbedShowLayout;

    emitted declarations:

    export default TabbedShowLayout;
    /**
     * @type {React.FunctionComponent}
     */
    declare const TabbedShowLayout: React.FunctionComponent;
    declare namespace TabbedShowLayout {
        export const defaultProps: Partial<any> | undefined;
    }
    import React from "react";

    Errors:
    Cannot redeclare block-scoped variable 'TabbedShowLayout'.

  2. Bnaya commented on Oct 11, 2019

    @Bnaya

    Additional breakage with javascript:

    import React from "react";
    import PropTypes from "prop-types"
    
    const TabbedShowLayout = ({
    }) => {
        return (
            <div />
        );
    };
    
    TabbedShowLayout.propTypes = {
        version: PropTypes.number,
    
    };
    
    TabbedShowLayout.defaultProps = {
        tabs: undefined
    };
    
    export default TabbedShowLayout;

    d.ts:

    export default TabbedShowLayout;
    declare function TabbedShowLayout({}: {}): JSX.Element;
    declare namespace TabbedShowLayout {
        export namespace propTypes {
            import version = PropTypes.number;
            export { version };
        }
        export namespace defaultProps {
    // Cannot export 'undefined'. Only local declarations can be exported from a module
            export { undefined as tabs };
        }
    // Import declarations in a namespace cannot reference a module.ts(1147)
    // Cannot find module 'prop-types'.ts(2307)
        import PropTypes from "prop-types";
    }
  3. Bnaya commented on Oct 11, 2019

    @Bnaya

    I'm not sure how common is it to emit invalid types
    But i think it will be very useful if the emitter would check the declarations it emits as a fail safe,
    and warn the user what something went wrong. maybe prompt to open an issue or so.

  4. Bnaya commented on Oct 15, 2019

    @Bnaya

    Is it on the roadmap to 3.7 final?

  5. weswigham commented on Oct 15, 2019

    @weswigham
    MemberAuthor

    It should be, yeah - I'm just on vacation this week, so probably won't progress on it for a bit.

  6. Bnaya commented on Oct 25, 2019

    @Bnaya

    I hope this issue won't be forgotten for 3.7 🙏😰

  7. weswigham commented on Oct 28, 2019

    @weswigham
    MemberAuthor

    Bnaya Peretz (@Bnaya) I have a build over in #34786 that I'd love if you could give a try.

  8. Bnaya commented on Oct 29, 2019

    @Bnaya

    Thank you very much!
    seems like most of the issues are gone

    some of the findings:

    import React from 'react';
    import PropTypes from 'prop-types';
    
    function Tree({ allowDropOnRoot }) {
      return <div />
    }
    
    Tree.propTypes = {
        classes: PropTypes.object,
    };
    
    Tree.defaultProps = {
        classes: {},
        parentSource: 'parent_id',
    };
    
    export default Tree;

    emits broken:

    export default Tree;
    declare function Tree({ allowDropOnRoot }: {
        allowDropOnRoot: any;
    }): JSX.Element;
    declare namespace Tree {
        export namespace propTypes {
            export const classes: PropTypes.Requireable<object>;
        }
        export namespace defaultProps {
     // Cannot find name 'classes_1'
            export { classes_1 as classes };
            export const parentSource: string;
        }
    }
    import PropTypes from "prop-types";
    //# sourceMappingURL=Tree.d.ts.map

    When removing the propTypes.classes the problem is gone.

    EDIT:
    Also it depends on the namespace for the prop-types module and not importing it,
    even that on the source, its importing it

  9. weswigham commented on Oct 30, 2019

    @weswigham
    MemberAuthor

    Bnaya Peretz (@Bnaya) there should be another build over in #34786 that also fixes that.

  10. Bnaya commented on Oct 30, 2019

    @Bnaya

    Works!

    Thank you!

  11. Bnaya commented on Nov 8, 2019

    @Bnaya

    Probably a related issue:
    #34994

  12. locked as resolved and limited conversation to collaborators on Oct 21, 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 files

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions