1

I have another NodeJS app built with typescript and global.d.ts file everything works fine but my new application is giving error while running with ts-node-dev ts-main-file.ts

In new application I have global.d.ts file in src folder but its not recognized.

global.d.ts file contents

declare namespace NodeJS {
  export interface Global {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    sequelize: any;
  }
}

tsconfig.json file contents

{
  "extends": "@tsconfig/node14/tsconfig.json",

  "compilerOptions": {
    "resolveJsonModule": true,
    "preserveConstEnums": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "noFallthroughCasesInSwitch": true,
    "allowSyntheticDefaultImports": true,
    "outDir": "out/build",
    "types": ["reflect-metadata"]
  },
  "include": ["src/**/*", "tests/**/*"],
  "exclude": ["node_modules", "**/*.spec.ts"]
}

I don't know why it is not working but if someone can point out the missing piece then that will be lot more helpful.

Environment Details: Node JS 15 ts-node-dev ver. 1.1.1 (using ts-node ver. 9.1.1, typescript ver. 4.1.3) Linux (Pop OS 20.10)

Code snippet of file where I see the error:

async connectWithDB() {
    const databaseName = 'local_server';
    const userName = 'test';
    const password = 'Test123$';
    const host = 'localhost';
    const dialect = 'postgres';

    global.sequelize = new Sequelize(databaseName, userName, password, {
      host: host,
      dialect: dialect,
      pool: {
        max: 50,
        min: 0,
        acquire: 30000,
        idle: 10000,
      },
      define: {
        charset: 'utf8',
      },
    });

    try {
      await global.sequelize.authenticate();
      console.log('Connection has been established successfully.');
    } catch (error) {
      console.error('Unable to connect to the database:', error);

      process.exit(1);
    }
  }
Sudhir Dhumal
  • 902
  • 11
  • 22
  • Your provided info isn't enough please provide the content of the related file or modules such as: `ts-main-file.ts` in your description by editing it. Maybe you used a undefined property of `this` or `type: GlobalThis` which isn't caught by VS-Code/IDE but you're still getting error while compiling. Remember global `this` of Browser & NodeJs are different – KR Tirtho Jan 03 '21 at 18:35
  • Edited answer with code snippet of ts-main-fie.ts – Sudhir Dhumal Jan 03 '21 at 18:59
  • in above code snippet If I change from `global.sequelize` to `const sequelize = ....` then everything is working fine – Sudhir Dhumal Jan 03 '21 at 19:07
  • Where is `global.d.ts`? Is it under `src`? It's not clear why you're using `include` at all though.... – Aluan Haddad Jan 03 '21 at 19:52
  • global.d.ts is directly placed under the src folder. Don't we need `include` to point to src directory for typescript to look into? – Sudhir Dhumal Jan 03 '21 at 20:12
  • No you don't need that. – Aluan Haddad Jan 03 '21 at 20:17
  • You should not pollute `global this` with sequelize or other APIs. Try to avoid this. It's not a good practice. Instead use a separate file for it & then import it to other files or simply return the `Sequelize` instance from the function – KR Tirtho Jan 04 '21 at 04:25
  • Yeah I already extracted it in separate file and now with the help of static I'm returning the same same instance but I'm still curious to know why adding something in global is not working – Sudhir Dhumal Jan 04 '21 at 04:33

3 Answers3

0

Using global thisor adding properties to it might cause issues later on. connectWithDB would also leave a side effect to the global chain of Nodejs. Also it'd create multiple instance of the same object. So just return the Sequelize instance if the authentication is successful else throw a Error & end the process

async connectWithDB() {
    const databaseName = 'local_server';
    const userName = 'test';
    const password = 'Test123$';
    const host = 'localhost';
    const dialect = 'postgres';

    const sequelize = new Sequelize(databaseName, userName, password, {
      host: host,
      dialect: dialect,
      pool: {
        max: 50,
        min: 0,
        acquire: 30000,
        idle: 10000,
      },
      define: {
        charset: 'utf8',
      },
    });

    try {
      await sequelize.authenticate();
      console.log('Connection has been established successfully.');
      return sequelize; //return the instance if you wanna use it elsewhere..
    } catch (error) {
      console.error('Unable to connect to the database:', error);

      process.exit(1);
    }
  }

On your top file of project hierarchy.. If you're using express

//main.ts / server.ts etc...
import express, {Request, Response} from 'express';
const app = express();
app.set(...);
.....
.....
export const dbConnect = connectWithDB();

app.get("/route", async (req:Request, res: Response)=>{
  dbConnection.then((db)=>{
    // do whatever
   }
  )
})

Or add it to the express request object..

app.use((req:Request, _, done)=>{
  dbConnection.then((db)=>{
    req.db=dbConnection;
     done();
   }
});

Now it will be available to all routes as req.db

KR Tirtho
  • 447
  • 5
  • 13
  • Alternate approach is perfectly fine but I still cant put anything in global scope. Rather than setting in request object I created static variable as mentioned in my previous comment and its working they way it should. But I'm still curious to know why setting something in global scope is not working. – Sudhir Dhumal Jan 10 '21 at 12:12
  • I think this is because of `typescript`. Because you added `dom` & `dom.iterable` in `lib` property of `tsconfig.json`. If you aren't working in browser environment then don't use this libs as `Nodejs` doesn't support `DOM` manipulation thus `global` is not recognized by `ts-node`. Try removing those from the array & let me know what happen... – KR Tirtho Jan 11 '21 at 04:04
  • Read this thread you might get an idea about the `lib` property of `tsconfig.json`: https://stackoverflow.com/questions/39303385/what-does-the-tsconfig-option-lib-do – KR Tirtho Jan 11 '21 at 04:06
  • I did remove both the dom & dom.iterable from config when I realized that I dont need them but even after that I cant use the global variable – Sudhir Dhumal Jan 15 '21 at 21:01
  • Updated my post with the latest tsconfig.json – Sudhir Dhumal Jan 15 '21 at 21:02
0

Try to use this.

declare global {
  var sequelize: any;

}

instead of

declare namespace NodeJS {
  export interface Global {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    sequelize: any;
  }
}
thilina
  • 61
  • 4
0
declare global {
   function signin(): Promise<string[]>;
   sequelize: any
}
global.signin = () => {};
global.sequelize = anything;

this will work hopefully