title: TypeScript metadata reflection references other classes before they are defined
body: <p>I have some TypeORM entities in my codebase which have relations to each other, making a circular dependency. Since decorator metadata is used on each entity class, TypeScript inserts code after each class defining metadata on it. Say that the classes are <code>Business</code> and <code>Qualification</code>. On the relating fields TypeScript will emit code that looks like this:</p>
  
  <pre><code>var __decorate = (this &amp;&amp; this.__decorate) || function (decorators, target, key, desc) {
      var c = arguments.length, r = c &lt; 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
      if (typeof Reflect === "object" &amp;&amp; typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
      else for (var i = decorators.length - 1; i &gt;= 0; i--) if (d = decorators[i]) r = (c &lt; 3 ? d(r) : c &gt; 3 ? d(target, key, r) : d(target, key)) || r;
      return c &gt; 3 &amp;&amp; r &amp;&amp; Object.defineProperty(target, key, r), r;
  };
  var __metadata = (this &amp;&amp; this.__metadata) || function (k, v) {
      if (typeof Reflect === "object" &amp;&amp; typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
  };
  const decorator = (target, thing) =&gt; {
  };
  class Business {
  }
  class Qualification {
  }
  __decorate([
      decorator,
      __metadata("design:type", Business)
  ], Qualification.prototype, "business", void 0);
  </code></pre>
  
  <p>This would all be fine, except the <code>__decorate</code> part always comes after each class, meaning that one of the classes is going to have to be used before it's defined, which causes an error. Here's a shortened version of the actual code with the actual error:</p>
  
  <pre class="lang-js prettyprint-override"><code>let Qualification = (_dec = Object(external_typeorm_["Entity"])(), _dec2 = Object(external_typeorm_["PrimaryGeneratedColumn"])(), _dec3 = Reflect.metadata("design:type", Number), _dec4 = Object(external_typeorm_["Column"])({
    nullable: true
  }), _dec5 = Object(external_class_validator_["IsOptional"])(), _dec6 = Object(external_class_validator_["IsUrl"])(), _dec7 = Reflect.metadata("design:type", String), _dec8 = Object(external_typeorm_["ManyToOne"])(type =&gt; Business["c" /* default */], business =&gt; business.qualifications, {
    onDelete: 'CASCADE'
  }), _dec9 = Reflect.metadata("design:type", typeof Business["c" /* default */] === "undefined" ?
  
                                                  // ^ TypeError: cannot read property "c" of undefined
  
  
  
   Object : Business["c" /* default */]), _dec10 = Object(external_typeorm_["Column"])({
    type: 'enum',
    enum: VALIDITY_STATES,
    default: 'invalid'
  }), _dec11 = Object(external_class_validator_["IsIn"])(VALIDITY_STATES), _dec12 = Reflect.metadata("design:type", Object), _dec13 = Object(external_typeorm_["Column"])('simple-json'), _dec14 = Object(external_class_validator_["ValidateNested"])(), _dec15 = Object(external_class_validator_["IsArray"])(), _dec16 = Object(external_class_validator_["IsIn"])(category["a" /* CATEGORIES */].filter(c =&gt; c.type === 'service').map(c =&gt; c.slug), {
    each: true
  }), _dec17 = Reflect.metadata("design:type", Array), _dec(_class = (_class2 = (_temp = class Qualification {
    constructor() {
      _initializerDefineProperty(this, "id", _descriptor, this);
  
      _initializerDefineProperty(this, "imageUrl", _descriptor2, this);
  
      _initializerDefineProperty(this, "business", _descriptor3, this);
  
      _initializerDefineProperty(this, "validity", _descriptor4, this);
  
      _initializerDefineProperty(this, "categories", _descriptor5, this);
    }
  
  }, _temp), (_descriptor = _applyDecoratedDescriptor(_class2.prototype, "id", [_dec2, _dec3], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, "imageUrl", [_dec4, _dec5, _dec6, _dec7], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor3 = _applyDecoratedDescriptor(_class2.prototype, "business", [_dec8, _dec9], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor4 = _applyDecoratedDescriptor(_class2.prototype, "validity", [_dec10, _dec11, _dec12], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor5 = _applyDecoratedDescriptor(_class2.prototype, "categories", [_dec13, _dec14, _dec15, _dec16, _dec17], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  })), _class2)) || _class);
  </code></pre>
  
  <p>Later in the code, <code>Business</code> is defined, but it's too late:</p>
  
  <pre class="lang-js prettyprint-override"><code>let Business = (_dec6 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Entity"])(), _dec7 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])(), _dec8 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsString"])(), _dec9 = Reflect.metadata("design:type", String), _dec10 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])({
    type: 'enum',
    enum: BUSINESS_TYPES
  }), _dec11 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsIn"])(BUSINESS_TYPES), _dec12 = Reflect.metadata("design:type", Object), _dec13 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])(), _dec14 = Reflect.metadata("design:type", Boolean), _dec15 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["CreateDateColumn"])(), _dec16 = Reflect.metadata("design:type", typeof Date === "undefined" ? Object : Date), _dec17 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])({
    nullable: true
  }), _dec18 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsOptional"])(), _dec19 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsUrl"])(), _dec20 = Reflect.metadata("design:type", String), _dec21 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])({
    nullable: true
  }), _dec22 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsOptional"])(), _dec23 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsString"])(), _dec24 = Reflect.metadata("design:type", String), _dec25 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])({
    nullable: true
  }), _dec26 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsOptional"])(), _dec27 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsString"])(), _dec28 = Reflect.metadata("design:type", String), _dec29 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])(), _dec30 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsString"])(), _dec31 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["MaxLength"])(200), _dec32 = Reflect.metadata("design:type", String), _dec33 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["OneToMany"])(type =&gt; _db_all_entities__WEBPACK_IMPORTED_MODULE_3__[/* Qualification */ "i"], qualification =&gt; qualification.business, {
    cascade: true
  }), _dec34 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["ValidateNested"])(), _dec35 = Reflect.metadata("design:type", Array), _dec36 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])('simple-json'), _dec37 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsArray"])(), _dec38 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["ValidateNested"])(), _dec39 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsIn"])(_misc_types_category__WEBPACK_IMPORTED_MODULE_2__[/* CATEGORIES */ "a"].filter(c =&gt; c.type === 'business').map(c =&gt; c.slug), {
    each: true
  }), _dec40 = Reflect.metadata("design:type", Array), _dec41 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])('simple-json'), _dec42 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsArray"])(), _dec43 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["ValidateNested"])(), _dec44 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["ArrayMinSize"])(1), _dec45 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["ArrayMaxSize"])(5), _dec46 = Reflect.metadata("design:type", Array), _dec47 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])({
    type: 'enum',
    enum: PRICING_PLANS
  }), _dec48 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsIn"])(PRICING_PLANS), _dec49 = Reflect.metadata("design:type", String), _dec50 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["OneToMany"])(type =&gt; _db_all_entities__WEBPACK_IMPORTED_MODULE_3__[/* BaseOffer */ "b"], offer =&gt; offer.offerer), _dec51 = Reflect.metadata("design:type", Array), _dec6(_class3 = (_class4 = (_temp2 = class Business extends _db_all_entities__WEBPACK_IMPORTED_MODULE_3__[/* Account */ "a"] {
    constructor(...args) {
      super(...args);
  
      _initializerDefineProperty(this, "name", _descriptor3, this);
  
      _initializerDefineProperty(this, "type", _descriptor4, this);
  
      _initializerDefineProperty(this, "isApproved", _descriptor5, this);
  
      _initializerDefineProperty(this, "since", _descriptor6, this);
  
      _initializerDefineProperty(this, "logoUrl", _descriptor7, this);
  
      _initializerDefineProperty(this, "fein", _descriptor8, this);
  
      _initializerDefineProperty(this, "phoneNumber", _descriptor9, this);
  
      _initializerDefineProperty(this, "bio", _descriptor10, this);
  
      _initializerDefineProperty(this, "qualifications", _descriptor11, this);
  
      _initializerDefineProperty(this, "businessCategories", _descriptor12, this);
  
      _initializerDefineProperty(this, "geolocations", _descriptor13, this);
  
      _initializerDefineProperty(this, "pricingPlan", _descriptor14, this);
  
      _initializerDefineProperty(this, "offers", _descriptor15, this);
    }
  
  }, _temp2), (_descriptor3 = _applyDecoratedDescriptor(_class4.prototype, "name", [_dec7, _dec8, _dec9], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor4 = _applyDecoratedDescriptor(_class4.prototype, "type", [_dec10, _dec11, _dec12], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor5 = _applyDecoratedDescriptor(_class4.prototype, "isApproved", [_dec13, _dec14], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor6 = _applyDecoratedDescriptor(_class4.prototype, "since", [_dec15, _dec16], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor7 = _applyDecoratedDescriptor(_class4.prototype, "logoUrl", [_dec17, _dec18, _dec19, _dec20], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor8 = _applyDecoratedDescriptor(_class4.prototype, "fein", [_dec21, _dec22, _dec23, _dec24], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor9 = _applyDecoratedDescriptor(_class4.prototype, "phoneNumber", [_dec25, _dec26, _dec27, _dec28], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor10 = _applyDecoratedDescriptor(_class4.prototype, "bio", [_dec29, _dec30, _dec31, _dec32], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor11 = _applyDecoratedDescriptor(_class4.prototype, "qualifications", [_dec33, _dec34, _dec35], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor12 = _applyDecoratedDescriptor(_class4.prototype, "businessCategories", [_dec36, _dec37, _dec38, _dec39, _dec40], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor13 = _applyDecoratedDescriptor(_class4.prototype, "geolocations", [_dec41, _dec42, _dec43, _dec44, _dec45, _dec46], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor14 = _applyDecoratedDescriptor(_class4.prototype, "pricingPlan", [_dec47, _dec48, _dec49], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor15 = _applyDecoratedDescriptor(_class4.prototype, "offers", [_dec50, _dec51], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  })), _class4)) || _class3);
  </code></pre>
  
  <p>Strangely, the code works when compiled for development mode because <code>Business</code> is not referred to directly but rather through a module constant. Here's how <code>Qualification</code> is defined in development mode:</p>
  
  <pre class="lang-js prettyprint-override"><code>let Qualification = (_dec = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Entity"])(), _dec2 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["PrimaryGeneratedColumn"])(), _dec3 = Reflect.metadata("design:type", Number), _dec4 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])({
    nullable: true
  }), _dec5 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsOptional"])(), _dec6 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsUrl"])(), _dec7 = Reflect.metadata("design:type", String), _dec8 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["ManyToOne"])(type =&gt; _db_all_entities__WEBPACK_IMPORTED_MODULE_2__["Business"], business =&gt; business.qualifications, {
    onDelete: 'CASCADE'
  }), _dec9 = Reflect.metadata("design:type", typeof _db_all_entities__WEBPACK_IMPORTED_MODULE_2__["Business"] === "undefined" ? Object : _db_all_entities__WEBPACK_IMPORTED_MODULE_2__["Business"]), _dec10 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])({
    type: 'enum',
    enum: VALIDITY_STATES,
    default: 'invalid'
  }), _dec11 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsIn"])(VALIDITY_STATES), _dec12 = Reflect.metadata("design:type", Object), _dec13 = Object(typeorm__WEBPACK_IMPORTED_MODULE_1__["Column"])('simple-json'), _dec14 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["ValidateNested"])(), _dec15 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsArray"])(), _dec16 = Object(class_validator__WEBPACK_IMPORTED_MODULE_0__["IsIn"])(_misc_types_category__WEBPACK_IMPORTED_MODULE_5__["CATEGORIES"].filter(c =&gt; c.type === 'service').map(c =&gt; c.slug), {
    each: true
  }), _dec17 = Reflect.metadata("design:type", Array), _dec(_class = (_class2 = (_temp = class Qualification {
    constructor() {
      _initializerDefineProperty(this, "id", _descriptor, this);
  
      _initializerDefineProperty(this, "imageUrl", _descriptor2, this);
  
      _initializerDefineProperty(this, "business", _descriptor3, this);
  
      _initializerDefineProperty(this, "validity", _descriptor4, this);
  
      _initializerDefineProperty(this, "categories", _descriptor5, this);
    }
  
  }, _temp), (_descriptor = _applyDecoratedDescriptor(_class2.prototype, "id", [_dec2, _dec3], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, "imageUrl", [_dec4, _dec5, _dec6, _dec7], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor3 = _applyDecoratedDescriptor(_class2.prototype, "business", [_dec8, _dec9], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor4 = _applyDecoratedDescriptor(_class2.prototype, "validity", [_dec10, _dec11, _dec12], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor5 = _applyDecoratedDescriptor(_class2.prototype, "categories", [_dec13, _dec14, _dec15, _dec16, _dec17], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  })), _class2)) || _class);
  </code></pre>
  
  <p>The actual code itself imports modules from an <code>all-entities.ts</code> file, which exports all the entities in the correct order so that superclasses don't accidentally get loaded after their subclasses, causing errors. That file looks like this (simplified):</p>
  
  <pre class="lang-js prettyprint-override"><code>export { default as Qualification } from '../entities/Qualification';
  export { default as Business } from '../entities/Business';
  </code></pre>
  
  <p><code>./entities/Qualification.ts</code> and <code>./entities/Business.ts</code> are both files that contain a default export of a TypeORM entity, and I don't feel like they're worth including here but I can if anyone wants to look at them. Here's the difference between my production and development webpack configs (generated by Next.js):</p>
  
  <pre><code>diff --git a/webpack-config-dev.txt b/webpack-config-prod.txt
  index f8a28c3..8e5fa4d 100644
  --- a/webpack-config-dev.txt
  +++ b/webpack-config-prod.txt
  @@ -1,80 +1,82 @@
   {
     externals: [ [Function] ],
     optimization: {
       checkWasmTypes: false,
       nodeEnv: false,
       splitChunks: false,
       runtimeChunk: undefined,
       minimize: false,
       minimizer: [ [TerserPlugin], [CssMinimizerPlugin] ]
     },
     context: 'C:\\Users\\Robbie\\Code\\fit-society',
     node: { setImmediate: false },
     entry: [AsyncFunction: entry],
     output: {
       path: 'C:\\Users\\Robbie\\Code\\fit-society\\.next\\server',
       filename: [Function: filename],
       libraryTarget: 'commonjs2',
       hotUpdateChunkFilename: 'static/webpack/[id].[hash].hot-update.js',
       hotUpdateMainFilename: 'static/webpack/[hash].hot-update.json',
  -    chunkFilename: '[name].js',
  +    chunkFilename: '[name].[contenthash].js',
       strictModuleExceptionHandling: true,
       crossOriginLoading: undefined,
  -    futureEmitAssets: false,
  +    futureEmitAssets: true,
       webassemblyModuleFilename: 'static/wasm/[modulehash].wasm'
     },
     performance: false,
     resolve: {
       extensions: [
         '.tsx',  '.ts',
         '.js',   '.mjs',
         '.jsx',  '.json',
         '.wasm'
       ],
       modules: [ 'node_modules' ],
       alias: {
         'next/head': 'next/dist/next-server/lib/head.js',
         'next/router': 'next/dist/client/router.js',
         'next/config': 'next/dist/next-server/lib/runtime-config.js',
         'next/dynamic': 'next/dist/next-server/lib/dynamic.js',
         next: 'C:\\Users\\Robbie\\Code\\fit-society\\node_modules\\next',
         'private-next-pages': 'C:\\Users\\Robbie\\Code\\fit-society\\src\\pages',
         'private-dot-next': 'C:\\Users\\Robbie\\Code\\fit-society\\.next'
       },
       mainFields: [ 'main', 'module' ],
       plugins: [ [Object] ]
     },
     resolveLoader: {
       alias: {
         'emit-file-loader': 'C:\\Users\\Robbie\\Code\\fit-society\\node_modules\\next\\dist\\build\\webpack\\loaders\\emit-file-loader',
         'error-loader': 'C:\\Users\\Robbie\\Code\\fit-society\\node_modules\\next\\dist\\build\\webpack\\loaders\\error-loader',
         'next-babel-loader': 'C:\\Users\\Robbie\\Code\\fit-society\\node_modules\\next\\dist\\build\\webpack\\loaders\\next-babel-loader',
         'next-client-pages-loader': 'C:\\Users\\Robbie\\Code\\fit-society\\node_modules\\next\\dist\\build\\webpack\\loaders\\next-client-pages-loader',
         'next-data-loader': 'C:\\Users\\Robbie\\Code\\fit-society\\node_modules\\next\\dist\\build\\webpack\\loaders\\next-data-loader',
         'next-serverless-loader': 'C:\\Users\\Robbie\\Code\\fit-society\\node_modules\\next\\dist\\build\\webpack\\loaders\\next-serverless-loader',
         'noop-loader': 'C:\\Users\\Robbie\\Code\\fit-society\\node_modules\\next\\dist\\build\\webpack\\loaders\\noop-loader',
         'next-plugin-loader': 'C:\\Users\\Robbie\\Code\\fit-society\\node_modules\\next\\dist\\build\\webpack\\loaders\\next-plugin-loader'
       },
       modules: [ 'node_modules' ],
       plugins: [ [Object] ]
     },
     module: {
       rules: [ [Object], [Object], [Object] ],
       strictExportPresence: true
     },
     plugins: [
       ChunkNamesPlugin {},
       DefinePlugin { definitions: [Object] },
  -    UnlinkRemovedPagesPlugin { prevAssets: {} },
  -    NoEmitOnErrorsPlugin {},
  -    NextJsRequireCacheHotReloader { prevAssets: null },
  +    HashedModuleIdsPlugin { options: [Object] },
  +    IgnorePlugin {
  +      options: [Object],
  +      checkIgnore: [Function: bound checkIgnore]
  +    },
       PagesManifestPlugin { serverless: false },
       NextJsSsrImportPlugin { options: [Object] },
       NextJsSsrImportPlugin {},
       FilterWarningsPlugin { exclude: [Array] }
     ],
  -  mode: 'development',
  +  mode: 'production',
     name: 'server',
     target: 'node',
  -  devtool: 'cheap-module-source-map'
  +  devtool: false
   }
  </code></pre>
  
  <p>Here are the classes that are causing the problem:
  Business.ts:</p>
  
  <pre class="lang-js prettyprint-override"><code>import {
    ArrayMaxSize,
    ArrayMinSize,
    IsArray,
    IsIn,
    IsOptional,
    IsString,
    IsUrl,
    MaxLength,
    ValidateNested,
    IsEmail
  } from 'class-validator';
  import { Column, CreateDateColumn, Entity, OneToMany } from 'typeorm';
  import { CATEGORIES } from '../../misc-types/category';
  import { Geolocation } from '../../misc-types/geolocation';
  import { Account, BaseOffer, Qualification, ValidateableQualification } from '../db/all-entities';
  import { omit } from './utils/entity-type-manipulations';
  import tuple from './utils/string-enum-from-tuple';
  
  const BUSINESS_TYPES = tuple('individual', 'company');
  const PRICING_PLANS = tuple('free');
  
  @Entity()
  export default class Business extends Account {
    /**
     * Public name for the business.
     */
    @Column()
    @IsString()
    name!: string;
  
    @Column({ type: 'enum', enum: BUSINESS_TYPES })
    @IsIn(BUSINESS_TYPES)
    type!: typeof BUSINESS_TYPES[number];
  
    @Column()
    isApproved!: boolean;
  
    /**
     * The date the business created their account (not when it was approved)
     */
    @CreateDateColumn()
    since!: Date;
  
    @Column({ nullable: true })
    @IsOptional()
    @IsUrl()
    logoUrl?: string;
  
    @Column({ nullable: true })
    @IsOptional()
    @IsString()
    fein?: string;
  
    @Column({ nullable: true })
    @IsOptional()
    @IsString()
    phoneNumber?: string;
  
    @Column()
    @IsString()
    @MaxLength(200)
    bio!: string;
  
    @OneToMany(
      type =&gt; Qualification,
      qualification =&gt; qualification.business,
      { cascade: true }
    )
    @ValidateNested()
    qualifications!: Qualification[];
  
    @Column('simple-json')
    @IsArray()
    @ValidateNested()
    @IsIn(
      CATEGORIES.filter(c =&gt; c.type === 'business').map(c =&gt; c.slug),
      { each: true }
    )
    businessCategories!: string[];
  
    /**
     * Places this business is available at
     */
    @Column('simple-json')
    @IsArray()
    @ValidateNested()
    @ArrayMinSize(1)
    @ArrayMaxSize(5)
    geolocations!: Geolocation[];
  
    @Column({ type: 'enum', enum: PRICING_PLANS })
    @IsIn(PRICING_PLANS)
    pricingPlan!: 'free';
  
    @OneToMany(
      type =&gt; BaseOffer,
      offer =&gt; offer.offerer
    )
    offers!: BaseOffer[];
  }
  
  /**
   * A DTO sent to change business properties, most of which align one-to-one (excluding password/passwordHash).
   */
  export class EditableBusiness extends omit(Business, [
    'id',
    'since',
    'isApproved',
    'qualifications',
    'passwordHash',
    'offers'
  ]) {
    @IsString()
    password!: string;
  }
  
  export class BusinessApplication extends EditableBusiness {
    @ValidateNested()
    @IsOptional()
    initialQualification!: ValidateableQualification;
  }
  </code></pre>
  
  <p>And in Qualification.ts:</p>
  
  <pre class="lang-js prettyprint-override"><code>import { IsJSON, IsUrl, ValidateNested, IsOptional, IsBoolean, IsIn, IsArray } from 'class-validator';
  import { Column, Entity, PrimaryGeneratedColumn, ManyToOne } from 'typeorm';
  import { Business } from '../db/all-entities';
  import tuple from './utils/string-enum-from-tuple';
  import { omit } from './utils/entity-type-manipulations';
  import { CATEGORIES } from '../../misc-types/category';
  
  const VALIDITY_STATES = tuple('valid', 'pending-review', 'invalid');
  
  @Entity()
  export default class Qualification {
    @PrimaryGeneratedColumn()
    id!: number;
  
    @Column({ nullable: true })
    // businesses do not need image proof
    @IsOptional()
    @IsUrl()
    imageUrl?: string;
  
    @ManyToOne(
      type =&gt; Business,
      business =&gt; business.qualifications,
      { onDelete: 'CASCADE' }
    )
    business!: Business;
  
    @Column({ type: 'enum', enum: VALIDITY_STATES, default: 'invalid' })
    @IsIn(VALIDITY_STATES)
    validity!: typeof VALIDITY_STATES[number];
  
    /**
     * The categories (slugs)
     */
    @Column('simple-json')
    @ValidateNested()
    @IsArray()
    @IsIn(
      CATEGORIES.filter(c =&gt; c.type === 'service').map(c =&gt; c.slug),
      { each: true }
    )
    categories!: string[];
  }
  
  /**
   * A qualification that can be sent by a business which is not necessarily verified yet.
   */
  export const ValidateableQualification = omit(Qualification, ['id', 'business', 'validity']);
  export type ValidateableQualification = typeof ValidateableQualification extends new () =&gt; infer U ? U : never;
  </code></pre>
  
  <p>Whenever either of these classes are imported, they're imported from this file to ensure the proper module loading order:</p>
  
  <pre class="lang-js prettyprint-override"><code>/* eslint-disable import/first */
  /**
   * This file exists to solve circular dependency problems with Webpack by explicitly specifying the module loading order.
   * @see https://medium.com/visual-development/how-to-fix-nasty-circular-dependency-issues-once-and-for-all-in-javascript-typescript-a04c987cf0de
   */
  
  export { default as Qualification, ValidateableQualification } from '../entities/Qualification';
  
  export { default as Account } from '../entities/Account';
  export { default as Business, EditableBusiness, BusinessApplication } from '../entities/Business';
  export { default as Customer } from '../entities/Customer';
  
  export { default as BaseOffer } from '../entities/Offer';
  
  import ProductOffer, { EditableProductOffer } from '../entities/ProductOffer';
  import ServiceOffer, { EditableServiceOffer } from '../entities/ServiceOffer';
  
  export { default as ProductOffer, EditableProductOffer } from '../entities/ProductOffer';
  export { default as ServiceOffer, EditableServiceOffer } from '../entities/ServiceOffer';
  
  export type Offer = ProductOffer | ServiceOffer;
  export type EditableOffer = EditableProductOffer | EditableServiceOffer;
  </code></pre>
  
  <p>Babel is also used in this project. Here's the .babelrc:</p>
  
  <pre><code>{
    "presets": [
      [
        "next/babel",
        {
          "class-properties": {
            "loose": true
          },
          "styled-jsx": {
            "plugins": [
              "styled-jsx-plugin-postcss"
            ]
          }
        }
      ]
    ],
    "plugins": [
      "babel-plugin-transform-typescript-metadata",
      [
        "@babel/plugin-proposal-decorators",
        {
          "legacy": true
        }
      ]
    ]
  }
  </code></pre>
  
  <p>Sorry for the huge wads of code. Could anybody help me try to solve this and figure out how to make it work in production like it works in development? Thanks.</p>