我正在阅读如下代码:
import { MongoMemoryServer } from "mongodb-memory-server";
import mongoose from "mongoose";
import request from "supertest";
import { app } from "../app";
declare global {
function signin(): Promise<string[]>;
}
let mongo: any;
beforeAll(async () => {
process.env.JWT_KEY = "asdfasdf";
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
const mongo = await MongoMemoryServer.create();
const mongoUri = mongo.getUri();
await mongoose.connect(mongoUri, {});
});
beforeEach(async () => {
const collections = await mongoose.connection.db.collections();
for (let collection of collections) {
await collection.deleteMany({});
}
});
afterAll(async () => {
if (mongo) {
await mongo.stop();
}
await mongoose.connection.close();
});
global.signin = async () => {
const email = "test@test.com";
const password = "password";
const response = await request(app)
.post("/api/users/signup")
.send({
email,
password,
})
.expect(201);
const cookie = response.get("Set-Cookie");
return cookie;
};
我不明白global.signin
函数的用途以及它是如何工作的?我想这与Jest
有关,但只要我知道Jest代码应该在具有相同文件名和.test.ts
扩展名的__test__
文件夹中。但是上面的函数是在应用程序根目录中的setup.ts
文件中定义和使用的。
我也看到一些代码如下:
declare global {
namespace Express {
interface Request {
currentUser?: UserPayload;
}
}
}
在我不确定的项目的一些.ts
文件中,这些global
变量与我上面提到的其他global
变量相同还是不同?我很想知道这个global
变量是如何工作的?
您共享的这段代码正在使用全局扩充https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-增强
// Hint typescript that your global object will have a custom signin function
declare global {
function signin(): Promise<string[]>;
}
// Assign value to global.signin
global.signin = async () => { /* implementation */ };
测试文件导入的一个或多个模块("mongoose"、"supertest"、"../app"(可能在某个时刻使用global.signin(或window.signin((或者它们的嵌套导入之一是=>在项目中查找"signin"(。因此,出于测试目的,需要对global.signin进行模拟。然而,仅仅添加global.signin = something
就会引发typescript错误,因为signin不是标准的全局变量。这就是declare global
发挥作用的地方。它提示typescript,在您的特定上下文中,signin
函数应该存在于全局范围中。
节点中运行的JavaScript/TypeScript将尝试解决在global
中当前本地作用域中找不到的任何内容(与浏览器在window
中的查找方式相同(。您可以全局访问的任何函数或变量(例如setTimeout()
(,也可以使用global.
作为前缀进行访问。它只是让它变得明确。
代码中发生的事情有两件:
declare global {
function signin(): Promise<string[]>;
}
这里它告诉typescript的类型系统global
对象还有一个名为signin
的函数。这部分不是必需的,但它是有意义的需要typescript来允许您访问/定义该函数,在JavaScript中您只需定义它。
https://www.typescriptlang.org/docs/handbook/declaration-merging.html提供了CCD_ 19如何工作的一些细节。
global.signin = async () => {
// code ...
};
在这里,它实际上被添加到全局对象中。
在JavaScript非严格模式下,您甚至可以编写(注意缺少var
/let
/const
/global.
(
signin = async () => {
// code ...
};
我没有看到signin
在代码中的任何地方被使用,所以我不清楚它的原因。只要定义它的文件被加载,你就可以简单地将其称为signin()
来调用函数。global.
是隐式添加的。
的目的
declare global {
namespace Express {
interface Request {
currentUser?: UserPayload;
}
}
}
更实用的是,在express中,您可能希望向中间件添加的请求添加属性。通过声明Express Request有一个名为currentUser
的属性,您就可以进行
app.get((req, res) => {
const user: UserPayload = req.currentUser
...
})
没有抱怨未知属性的typescript。举个例子https://blog.logrocket.com/extend-express-request-object-typescript/