【问题标题】:Typescript Node JS - `Property does not exist on type 'Global & typeof globalThis'`Typescript Node JS - `Global&typeof globalThis'类型上不存在属性`
【发布时间】:2021-04-09 16:12:49
【问题描述】:

我有另一个使用 typescript 和 global.d.ts 文件构建的 NodeJS 应用程序,一切正常,但我的新应用程序在使用 ts-node-dev ts-main-file.ts 运行时出错

在新应用程序中,我在 src 文件夹中有 global.d.ts 文件,但无法识别。

global.d.ts 文件内容

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

tsconfig.json 文件内容

{
  "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"]
}

我不知道为什么它不起作用,但如果有人能指出缺失的部分,那将更有帮助。

环境细节: 节点 JS 15 ts-node-dev 版本。 1.1.1(使用 ts-node 版本 9.1.1,打字稿版本 4.1.3) Linux(流行操作系统 20.10)

我看到错误的文件的代码 sn-p:

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);
    }
  }

【问题讨论】:

  • 您提供的信息不够,请在您的描述中提供相关文件或模块的内容,如:ts-main-file.ts 编辑。也许您使用了 thistype: GlobalThis 的未定义属性,它没有被 VS-Code/IDE 捕获,但您在编译时仍然遇到错误。请记住,浏览器和 NodeJ 的全局 this 是不同的
  • 使用 ts-main-fie.ts 的代码 sn-p 编辑答案
  • 在上面的代码 sn-p 如果我从 global.sequelize 更改为 const sequelize = .... 那么一切正常
  • global.d.ts 在哪里?是在src 下吗?目前尚不清楚您为什么要使用include....
  • global.d.ts 直接放在src文件夹下。我们不需要include 指向 src 目录以供打字稿查看吗?

标签: node.js typescript


【解决方案1】:
declare global {
   function signin(): Promise<string[]>;
   sequelize: any
}
global.signin = () => {};
global.sequelize = anything;

这很有希望

【讨论】:

    【解决方案2】:

    尝试使用它。

    declare global {
      var sequelize: any;
    
    }
    

    而不是

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

    【讨论】:

      【解决方案3】:

      使用global this或向其添加属性可能会在以后引起问题。 connectWithDB 也会给 Nodejs 的 global 链留下副作用。它还会创建同一对象的多个实例。因此,如果 authentication 成功则返回 Sequelize 实例,否则抛出错误并结束进程

      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);
          }
        }
      

      在项目层次结构的顶层文件中..如果您使用的是 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
         }
        )
      })
      

      或者添加到快递请求对象中..

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

      现在所有路线都可以使用req.db

      【讨论】:

      • 替代方法非常好,但我仍然不能将任何东西放在全局范围内。我没有在请求对象中设置,而是创建了我之前评论中提到的静态变量,并且它的工作方式应该如此。但我仍然很想知道为什么在全局范围内设置某些东西不起作用。
      • 我认为这是因为typescript。因为您在tsconfig.jsonlib 属性中添加了domdom.iterable。如果您不在浏览器环境中工作,请不要使用此库,因为Nodejs 不支持DOM 操作,因此global 无法被ts-node 识别。尝试从数组中删除这些并让我知道发生了什么...
      • 阅读此主题您可能会了解tsconfig.jsonlib 属性:stackoverflow.com/questions/39303385/…
      • 当我意识到我不需要它们时,我确实从配置中删除了 dom 和 dom.iterable,但即使在那之后我也无法使用全局变量
      • 用最新的 tsconfig.json 更新了我的帖子
      猜你喜欢
      • 2020-12-23
      • 2021-09-10
      • 2022-06-14
      • 2022-01-04
      • 2021-05-13
      • 2022-08-05
      • 2021-09-20
      • 2021-01-09
      • 2017-06-28
      相关资源
      最近更新 更多