Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

tsconfig.json compile problem when running mocha tests with overwritten global interfaces

I am trying to write tests for my nodejs server application and by now everything worked fine. I can compile my code from typescript to javascript without error and everything but when I try to run mocha tests the typescript pre-compilation fails due to not finding my self defined typings in typings.d.ts.

Here are my declarations inside the typings.d.ts

import {User} from "./users/user.model";
import {MainDatabase} from "./core/models/database.model";
import {Translation} from "./core/services/i18n";
import {LanguageDefinition} from "./core/models/language.model";
import {Reminder} from "./core/services/schedule/schedule.model";
import {UserProfileModel} from "./core/database/models/user_profile";
import {UserClientModel} from "./core/database/models/user_client";
import {PhoneNumberModel} from "./core/database/models/phone_number";
import {CountryModel} from "./core/database/models/country";
import {CustomerTypeModel} from "./core/database/models/customer/customer_type";
import {CustomerModel} from "./core/database/models/customer/customer";
import {ReminderModel} from "./core/database/models/reminder_options";
import {Customer} from "./customers/customer.model";
import {IUserAccount} from "./core/database/models/user_account";
import {UserAccountModel} from "./core/database/models/user_account";
import {MailModel} from "./core/services/mail/mail.model";
import {Request} from "express";
import {Models} from "sequelize";

declare global {
  module NodeJS {
    interface Global {
      translation: Translation;
      db: MainDatabase;

      /*Classes to be reach through the global object*/
      User: User;
      Reminder: Reminder;
      Customer: Customer;
      Mailer: MailModel;
    }
  }

}

declare module "Express"{
  export interface Request {
    user?: IUserAccount;
    authenticated: boolean;
    locals: {
      files?: File[];
    };
    locale?: LanguageDefinition;
    info?:{
      userAgent?: string;
      ip?: string;
    }
  }
}

// extending the original sequelize interfaces
declare module "sequelize" {

  /**
   * Database models
   * only list SEQUELIZE Models here not classes
   * */
  interface Models {
    UserProfile: UserProfileModel;
    UserAccount: UserAccountModel;
    UserClient: UserClientModel;
    Reminder: ReminderModel;
    PhoneNumber: PhoneNumberModel,
    CustomerType: CustomerTypeModel,
    Customer: CustomerModel,
    Country: CountryModel
  }
}

And in my app.ts I'm using those types by importing the original interface / type from the original package

//omitted for brevity
/**
 * Setup all globals that do not belong to the database
 * */
private setupServerGlobals() {
  try {
    global.Mailer = new MailModel();
  } catch (e) {
    console.error('setupServerGlobals', e);
  }
}

private setupTranslation(): Observable<any> {
  // create translation
  const translation = new Translation({
    language: { language: 'de', fullLanguage: 'de' },
  });
return translation.init().pipe(
  tap(() => {
    global.translation = translation;
  }),
);
}

Now when I run tsc --watch & nodemon ./dist/src/app.js all files are compiled successfully and the server starts without any problems. My global defined typings inside typings.d.ts are seen by the compiler due my tsconfig.json configuration.

But when I run tsc & mocha it throws this error:

/Users/user/Documents/Project/subfolder/project-name/node_modules/ts-node/src/index.ts:261
    return new TSError(diagnosticText, diagnosticCodes)
           ^
TSError: ⨯ Unable to compile TypeScript:
src/app.ts(60,14): error TS2339: Property 'Mailer' does not exist on type 'Global'.
src/app.ts(78,11): error TS2339: Property 'info' does not exist on type 'Request'.
src/app.ts(156,16): error TS2339: Property 'translation' does not exist on type 'Global'.

My setup looks like this: + I have all test files next to each to-be-tested file + I have an test folder where my mocha.opts file is in

Here the contents of my mocha.opts file:

src/**/*.spec.ts
--require ts-node/register
--recursive

And finally here is my tsconfig.json file:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "allowJs": true,
    "importHelpers": true,
    "jsx": "react",
    "alwaysStrict": true,
    "sourceMap": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitReturns": true,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "noImplicitAny": false,
    "noImplicitThis": false,
    "strictNullChecks": false,
    "outDir": "dist"
  },
  "include": ["**/*.ts"]
}

Expectation

To run my tests like it runs the server, without compiling problems.

I appreciate every help.

Edit

I could solve my problem by just importing the typings from typings.d.ts like so in my app.ts file

import * as typings from './typings';

But for me that just don't seem to be a good solution for this problem because in every file I'll use the global variable I'll need to reimport the typings like above.

Still feel free to solve this issue if you know how to.

like image 282
Hart Herbert Avatar asked Oct 18 '18 08:10

Hart Herbert


1 Answers

In my case, I inserted the following into tsconfig.json

{
  "ts-node": {
    "transpileOnly": true
  },
  "compilerOptions": {
    ...
  }
}

and it works.

like image 110
Daeki Yoon Avatar answered Nov 02 '22 17:11

Daeki Yoon