6

Lets say I have a JavaScript file(lib.js) which exports some classes, functions, etc etc.

export class Employment {
    id = "";
    startDate = "";
    endDate = "";
    companyEmailAddress = "";
};


export function HolidayPopupContainer() {
    return (<div id="#HolidayPopupContainer" />);
}

export default withStyles(styles)(Button);

export default class DayView extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            readOnly: false
        }


    };
export const Status = [
    "Select Status",
    "Pending",
    "Approved",
    "Rejected",
    "All"
]

Now this file is saved as lib.js in one of the folder. As this file has exports, those exported can be imported by other JavaScript files.

Is there a way where we can programmatically find the full list of exports from a JavaScript file.

The expected output should be a list/array/json etc. The output for the above mentioned js file would be

Employment
HolidayPopupContainer
withStyles
DayView 
Status 

Can Object.keys be of any help here?

Chetan
  • 4,735
  • 8
  • 48
  • 57
  • `import * as name from "module-name";` ... now `name.Employment`, `name.HolidayPopupContainer` etc is how you'd access he exports (name can be anything you want) - it's [all documented here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Syntax) – Jaromanda X Dec 04 '19 at 11:46
  • I haven't tried it so correct me if I'm wrong, but I think you should be able to do `import * as Lib from './lib'` then `Object.keys(Lib)`. You should remove the default keyword from some of your exports, though, because `default` will become a property on lib. – Kobe Dec 04 '19 at 11:47
  • You can use Object.keys if the objects attributes are what you're looking for, attributes in this case being your exported items ? – Pogrindis Dec 04 '19 at 11:47
  • 1
    @Kobe ... `import defaultExport, * as name from "module-name";`? – Jaromanda X Dec 04 '19 at 11:48
  • @JaromandaX I guess that would work, nice one. – Kobe Dec 04 '19 at 11:49
  • @JaromandaX `defaultExport` ?? Thats new to me! – Pogrindis Dec 04 '19 at 11:49
  • `defaultExport` is a name ... it could be `import fred, *` :p - read the documentation, I copied the line from that – Jaromanda X Dec 04 '19 at 11:51
  • By the way, you can not have two `export default` in one module – Jaromanda X Dec 04 '19 at 11:51
  • @Kobe ... using `import defaultExport, * as name from` you'll still have a `default` in `name` which will be the same export as `defaultExport` – Jaromanda X Dec 04 '19 at 11:58

2 Answers2

6

To start with, there should only be one default export in a module. If you fix that, and remove one of the default exports - say, you change DayView to a named export, then with

import * as LibNamespace from './lib.js'

you will have a (namespace) object whose properties are the named exports, plus the default property for the default export. For your code, the keys of this object will be

console.log(Object.keys(LibNamespace))
// ['Employment', 'HolidayPopupContainer', 'default', 'DayView', 'Status']

If you want withStyles to be "named", and included in the above instead of default, you'll need to change it to be a named export instead:

const exportedVar = withStyles(styles)(Button);
export { exportedVar as withStyles };

But that's kind of confusing, because it looks like you already have a variable named withStyles in scope there. Maybe call the exported variable something else:

export const buttonResult = withStyles(styles)(Button);

(or whatever you prefer)

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
1

As per documentation - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export, there can only be one default export per module.

Apart from above solutions, you can also use dynamic import to get exported names.

// some.js

export const name = "someName";

export class Employment {
    id = "";
    startDate = "";
    endDate = "";
    companyEmailAddress = "";
};

export function HolidayPopupContainer() {
    return "HolidayPopupContainer";
}

export default class DayView  {
    constructor() {

    }
}

export const Status = [
    "Select Status",
    "Pending",
    "Approved",
    "Rejected",
    "All"
]

// index.js

const exportedVar = [];

import('./some.js')
    .then(module => {
        const {default: defaultExport, ...rest} = module;
        exportedVar.push(defaultExport.name, ...Object.keys(rest));
        console.log(exportedVar);
    });

See - https://stackblitz.com/edit/js-yndmc6

random
  • 7,756
  • 3
  • 19
  • 25
  • Using your snippet to try to debug my exports, I got a "can't get 'name' of undefined" error for `defaultExport`. Otherwise, thank you very much. Your answer brought me great joy. – Boris Verkhovskiy Aug 16 '21 at 20:47