typescript-json-serializer: "Cannot use import statement outside a module" when using versions > 3.0

After microbundle was added to this package, I see the error SyntaxError: Cannot use import statement outside a module whenever I try to use this library. I was able to create a simple reproduction using the code from the README. Compiling and executing this:

import { Serializable, JsonProperty } from 'typescript-json-serializer'

@Serializable()
export class LivingBeing {

    @JsonProperty() id: number;
    constructor(id: number) {
        this.id = id;
        
    }
}

results in this error

/Users/darylwalleck/repos/ts-serializer-test/node_modules/typescript-json-serializer/dist/index.modern.js:1
import"reflect-metadata";function e(){return(e=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var a in r)Object.prototype.hasOwnProperty.call(r,a)&&(e[a]=r[a])}return e}).apply(this,arguments)}var t;function r(e){const t=Reflect.getPrototypeOf(e);return t&&t.name?[...r(t),t.name]:[]}function a(r){return(a,n,i)=>{if(void 0===n&&a.prototype){const e=Reflect.getMetadata("design:paramtypes",a)[i];n=function(e){const t=e.toString().replace(/(\/\*[\s\S]*?\*\/|\/\/.*$)/gm,"").replace(/[\r\t\n\v\f]/g,"").replace(/( +)/g," "),r=/(?:this\.)([^\n\r\t\f\v;]+)([\s;])/gm,a=new Map,n=/(?:.*(?:constructor|function).*?(?=\())(?:\()(.+?(?=\)))/m.exec(t);if(!n||!n.length)return a;const i=n[1].replace(/ /g,"").split(",");let o;for(;o=r.exec(t);){const e=o[1].replace(/ /g,"").split("="),t=i.findIndex(t=>t===e[1]);t>-1&&a.set(t,e[0])}return a}(a.prototype.constructor).get(i),a=a.prototype,Reflect.defineMetadata("design:type",e,a,n)}let o={};const s=`api:map:${a.constructor.name}`;Reflect.hasMetadata(s,a)&&(o=Reflect.getMetadata(s,a)),o[n]=function(r,a){if(!a)return{name:r.toString(),isDictionary:!1,isNameOverridden:!1};let n;return n=typeof a===t.String?{name:a,isNameOverridden:!0}:a.name?{name:a.name,isNameOverridden:!0}:a.names&&a.names.length?{names:a.names}:{name:r.toString(),isNameOverridden:!1},n=e({},n,{beforeSerialize:a.beforeSerialize,afterSerialize:a.afterSerialize,beforeDeserialize:a.beforeDeserialize,afterDeserialize:a.afterDeserialize,isDictionary:!!a.isDictionary}),e({},n,a.predicate?{predicate:a.predicate}:{type:a.type})}(n,r),Reflect.defineMetadata(s,o,a)}}function n(e){return t=>{const a=r(t);Reflect.defineMetadata("api:map:serializable",{baseClassNames:a,options:e},t)}}function i(t,r){let a={};return t.forEach(t=>{a=e({},a,Reflect.getMetadata(`api:map:${t}`,r))}),a}function o(r,a){var n;if([null,void 0].includes(r))return r;if(void 0===a)return l(typeof r,r);const s=new a,f=s.constructor.name,{baseClassNames:p,options:u}=null!=(n=Reflect.getMetadata("api:map:serializable",a))?n:{},d=`api:map:${f}`,m=Reflect.hasMetadata(d,s);let y={};return m||p&&p.length?(y=Reflect.getMetadata(d,s),p&&p.length&&(y=e({},i(p,s),y)),Object.keys(y).forEach(e=>{const a=function(e,r,a,n,i){let s;if([null,void 0].includes(n))return n;if("names"in a){const e={};a.names.forEach(t=>e[t]=n[t]),s=e}else if("name"in a&&!a.isNameOverridden&&i){const e=i(a.name);s=n[e]}else s=n[a.name];if([null,void 0].includes(s))return s;const f=Reflect.getMetadata("design:type",e,r),p=!!f.name&&f.name.toLowerCase()===t.Array,u=a.isDictionary,d=a.predicate,m=a.beforeDeserialize,y=a.afterDeserialize;let g=a.type||f;const b=c(g);let v;if(m&&(s=m(s,e)),u){const a={};typeof s!==t.Object?(console.error(`Type '${typeof s}' is not assignable to type 'Dictionary' for property '${r}' in '${e.constructor.name}'.\n`,`Received: ${JSON.stringify(s)}`),v=void 0):(Object.keys(s).forEach(t=>{b||d?(d&&(g=d(s[t],s)),a[t]=o(s[t],g)):a[t]=l(typeof s[t],s[t],r,e.constructor.name)}),v=a)}else if(p){const t=[];Array.isArray(s)?(s.forEach(a=>{b||d?(d&&(g=d(a,s)),t.push(o(a,g))):t.push(l(typeof a,a,r,e.constructor.name))}),v=t):(console.error(`Type '${typeof s}' is not assignable to type 'Array' for property '${r}' in '${e.constructor.name}'.\n`,`Received: ${JSON.stringify(s)}`),v=void 0)}else b||d?(g=d?d(s,n):g,v=o(s,g)):v=l(g.name,s,r,e.constructor.name);return y&&(v=y(v,e)),v}(s,e,y[e],r,null==u?void 0:u.formatPropertyNames);void 0!==a&&(s[e]=a)}),s):s}function s(r,a=!0){var n;if([void 0,null].includes(r)||typeof r!==t.Object)return r;const o=`api:map:${r.constructor.name}`,{baseClassNames:l,options:f}=null!=(n=Reflect.getMetadata("api:map:serializable",r.constructor))?n:{},p=l&&l.length,u=Reflect.hasMetadata(o,r);let d={};if(!u&&!p)return r;d=Reflect.getMetadata(o,r),p&&(d=e({},i(l,r),d));const m={},y=Object.keys(r);return Object.keys(d).forEach(e=>{if(y.includes(e)){const n=d[e],i=n.beforeSerialize,o=n.afterSerialize;let l;i&&(l=r[e],r[e]=i(r[e],r));let p=function(e,r,a,n){const i=e[r],o=Reflect.getMetadata("design:type",e,r),l=!!o.name&&o.name.toLocaleLowerCase()===t.Array,f=a.predicate,p=a.type||o,u=c(p);if(i&&(u||f)){if(l)return i.map(e=>s(e,n));if(a.isDictionary){const e={};return Object.keys(i).forEach(t=>{e[t]=s(i[t],n)}),e}return s(i,n)}return p.name.toLocaleLowerCase()===t.Date&&typeof i===t.Object?i.toISOString():i}(r,e,n,a);if(o&&(p=o(p,r)),r[e]=l||r[e],n.names)n.names.forEach(e=>{(!a||a&&void 0!==p[e])&&(m[e]=p[e])});else if(!a||a&&void 0!==p)if(!n.isNameOverridden&&null!=f&&f.formatPropertyNames){const e=f.formatPropertyNames(n.name);m[e]=p}else m[n.name]=p}}),m}function c(e){return Reflect.hasOwnMetadata("api:map:serializable",e)}function l(e,r,a,n){if(null==e)return r;if(e=e.toLowerCase(),(typeof r).toLowerCase()===e)return r;const i=()=>{console.error(`Type '${typeof r}' is not assignable to type '${e}' for property '${a}' in '${n}'.\n`,`Received: ${JSON.stringify(r)}`)};switch(e){case t.String:const e=r.toString();return"[object Object]"===e?void i():e;case t.Number:const a=+r;return isNaN(a)?void i():a;case t.Boolean:return void i();case t.Date:return isNaN(Date.parse(r))?void i():new Date(r);default:return r}}!function(e){e.Array="array",e.Boolean="boolean",e.Date="date",e.Number="number",e.Object="object",e.String="string"}(t||(t={}));export{a as JsonProperty,n as Serializable,o as deserialize,s as serialize};
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:355:18)
    at wrapSafe (node:internal/modules/cjs/loader:1022:15)
    at Module._compile (node:internal/modules/cjs/loader:1056:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1121:10)
    at Module.load (node:internal/modules/cjs/loader:972:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Module.require (node:internal/modules/cjs/loader:996:19)
    at require (node:internal/modules/cjs/helpers:92:18)
    at Object.<anonymous> (/Users/darylwalleck/repos/ts-serializer-test/dist/index.js:13:38)
    at Module._compile (node:internal/modules/cjs/loader:1092:14)

I’m not sure if this is a bug or an issue with my tsconfig.json . Here’s the config I’m using:

{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */
    "target": "es2020",
    "module": "commonjs",
    "strict": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "sourceMap": true,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "declaration": true,
  },
  "include": [
    "src/**/*"
  ]
}

Any feedback would be appreciated. Thanks!

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 20 (9 by maintainers)

Commits related to this issue

Most upvoted comments

I also ran into this problem and wanted to create an issue but came too late to the party 😉.

The reason for the problem is that microbundle (or whatever) wrote this to generated package.json as @raravel already mentioned:

"exports": "./dist/index.modern.js",

index.modern.js itself uses the ES modules syntax with import/export which is incompatible with Node. Instead of going back to rollup the following change would have been sufficient:

"exports": {
    "import": "./dist/index.modern.js",
    "require": "./dist/index.js"
},

This (and a gazillion of other options) is documented here: Modules: Packages.

In the meantime I got around the problem by patching package.json like above which made it possible to use and pack the serializer for the browser and Node without any further workarounds (using also rollup for both platforms).

I published a new 3.2.2 version, you can now download. Normally everything work properly.

I don’t know exactly why it failed, I replaced microbundle by rollup and tested with lot of configurations…

Hope it works for you!

I tried 14.16.0 (the current LTS) and I’m getting a very similar error:

❯ node ./dist/index.js
(node:47836) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/Users/darylwalleck/repos/ts-serializer-test/dist/index.js:10
import { Serializable, JsonProperty } from 'typescript-json-serializer';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
    at Module._compile (internal/modules/cjs/loader.js:1027:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
    at internal/main/run_main_module.js:17:47

If I roll back to 12.30.0, what you suggested works fine.