我有一个名为checkIsLoggedIn
的{{3}}函数,该函数可以验证请求中有一个Express middlewear并且该会话中有一个用户。如果不是,它将调用response.sendStatus(HttpStatus.FORBIDDEN)
。如果是这样,它会通过将request
字段设置为user
来扩充request.session.passport.user as MyUser
并调用next()
。
import { Request, RequestHandler, Router } from 'express';
import HttpStatus from 'http-status-codes';
import MyUser from './my-user';
interface PassportUser { /* ... */ }
interface ILoggedInRequest extends Request {
user: MyUser;
session: {
passport: {
user: PassportUser;
}
}
}
function transformUser(user: PassportUser): MyUser {
/* ... */
}
const checkIsLoggedIn: RequestHandler = function (req, res, next) {
let user: PassportUser | undefined =
req.session && req.session.passport && req.session.passport.user;
if (!user) {
res.sendStatus(HttpStatus.FORBIDDEN);
return;
}
req.user = transformUser(user);
next();
}
const router = Router();
router.get('/api/my/route', checkIsLoggedIn, (req, res) => {
// do stuff with req.user
});
是否可以告诉TypeScript编译器,在管道中调用checkIsLoggedIn
之后req
此时实现了ILoggedInRequest
?
很明显,我可以在我的匿名函数中声明req: ILoggedInRequest
...
router.get('/api/my/route', checkIsLoggedIn, (req: ILoggedInRequest, res) => {
// do stuff with req.user
});
...但是我有类似的中间件函数,它们附加了其他属性,因此我不想声明req: ILoggedInRequest & ISomeOtherRequest & IAnotherRequest
。更重要的是,我仍在学习TypeScript,并且好奇我问的问题是否可能。
我知道创建类型保护会在更一般的情况下产生这种情况...
function transformArg(myArg: any): myArg is IMyInterface {
myArg.foo = 'bar';
return true;
}
...尽管我对具有副作用的类型保护并不陌生-就像 really 并不疯狂;这似乎是一个可怕的想法-所以我想我的问题可以归结为两个问题:
我们可以避免类型保护滥用吗?换句话说,我们可以告诉编译器调用函数对其参数有副作用吗?
我们可以告诉编译器...
function myFunc(...pipelineFns: (myArg: IBaseInterface) => any): any;
...将依次调用每个pipelineFn
,产生那些副作用吗?
答案 0 :(得分:0)
另一个避免类型保护措施带来副作用的解决方案是返回具有不同类型的同一对象的“视图”。
一些想法:
function transformArg(myArg: Request): IMyInterface | null {
// ...
}
...一种用于检查请求是否已登录并返回myArg本身(例如,{{1})的函数。
我已经看到了类似的模式,其中返回“弱”类型以防止对象发生变异,例如:IMyInterface
,但是您可以两者都做。