Search code examples
javascriptecmascript-5

ES5 exported function not recognized


I got this math.js:

const sum = (a, b) => a + b
const mul = (a, b) => a * b

export default { sum, mul }

then in math.test.js:

const { sum, mul } = require('./math')

test('Adding 1 + 1 equals 2', () => {
  expect(sum(1, 1)).toBe(2)
})

test('Multiplying 1 * 1 equals 1', () => {
  expect(mul(1, 1)).toBe(1)
})

I got this error from jest:

? Adding 1 + 1 equals 2

  TypeError: sum is not a function

    5 | })
    6 | test('Adding 1 + 1 equals 2', () => {
  > 7 |   expect(sum(1, 1)).toBe(2)
    8 | })
    9 |

If I import those function in the test file, jest runs fine. Can't understand proper way to take external function in ES5.


Solution

  • There are two problems:

    1. This line probably doesn't do what you think it does:

      export default { sum, mul }
      
    2. You're mixing native module syntax (export/import, often called "ESM" for ECMAScript Modules) with CommonJS syntax (require). Use import to import in ESM syntax.

    export default { sum, mul } exports a default export that's an object with the properties sum and mul (which would be an odd thing to do with ESM). If that's really want you want to do, fine, but it's not usually best practice. You can't destructure on import, but you can destructure the object after importing it:

    // BUT YOU PROBABLY DON'T WANT TO DO THIS, KEEP READING
    import math from "./math"; // Imports that default export
    cosnt {sum, mul} = math;   // Destructures it into constants
    

    But, normally you'd use named exports, either as you go:

    export const sum = (a, b) => a + b
    export const mul = (a, b) => a * b
    

    ...or all at once (style decision):

    const sum = (a, b) => a + b
    const mul = (a, b) => a * b
    
    export { sum, mul };
    

    To import named exports, you'd use syntax like you did but with import, not require:

    import { sum, mul } from "./math";
    

    That's not destructuring, though it looks similar. It lacks several features of destructuring (nesting, default values, ...).

    Alternately you can import a namespace object:

    import * as math from "./math";
    

    That will have sum and mul properties on it (which is why you don't normally export an object with JavaScript native modules; anything that really wants one can get a namespace object).