我在 customExpress.d.ts
中有一个扩展类型:
declare namespace Express {
export interface Request {
user: {
id: string;
};
}
}
也在tsconfig.json中处理:
...
"typeRoots": ["src/customExpress.d.ts", "node_modules/@types"],
"files": ["src/customExpress.d.ts"],
...
我可以直接在 express 应用的中间件中使用它:
const app = express();
app.use('/authUrl', authenticationMiddleware);
具有以下定义:
const authenticationMiddleware = (req: express.Request, _: express.Response, next: express.NextFunction): void => {
...
req.user = {id: 'aaaaa'}
next();
}
export default authenticationMiddleware;
但是以下方法不起作用:
const authorize = (req: express.Request, _: express.Response, next: express.NextFunction): void => {
...
if (!req.user.id) {
next(new Error('not authorized'));
} else {
next();
}
}
以下用法时:
const routes = express.Router({ mergeParams: true });
routes.get('/', authorize, handler.listAll);
以上代码会报错:
authorize.ts(16,17): error TS2339: Property 'user' does not exist on type 'Request'.
所以它抱怨我在 authorize.ts 文件中定义的 req.user
的用法。
基本上,如果我在 express 对象中使用中间件,则自定义 express 对象可以正常工作,但是如果我想在 route 对象中使用自定义 express,它将不起作用。我的猜测是创建 routes
对象的方式(通过 express.Router
)不会识别我的自定义快递并回退到默认快递对象,因此自定义字段将不起作用。
我该怎么办?
答案 0 :(得分:0)
我不确定,但是类型定义只是在编译时要检查的东西,运行时没有类型,因为 js 是运行的,所以如果 req 中没有用户对象,它会抛出错误。
做你想做的事,我认为最好使用通行证,它进行你的身份验证,并在用户通过身份验证时附加一个用户对象。
答案 1 :(得分:0)
我终于意识到问题在于它的运行方式:
"start:stable": "rm -rf dist && npm run build && node -r ts-node/register -r tsconfig-paths/register dist/src",
"build": "tsc",
"start": "nodemon"
问题在于 npm run build
(基本上是 tsc
)成功构建代码。然而,第二部分 ts-node
尝试再次构建它。但是,在构建时,默认的 tsconfig.json
位置应该在目标文件夹中,即 dist/src
,当然不是那样。 tsc
不会按照配置处理 tsconfig.json
文件。因此,ts-node
无法处理代码,因为它没有 tsconfig
中提供的 typeRoot 定义。
解决办法是,由于我在tsc
之前已经在做ts-node
,所以不需要重复同样的工作,ts-node
只需要为{{1}做转译即可}}。
答案是将 node
命令更改为:
start:stable
我还发现了一些有趣的事情:默认情况下,rm -rf dist && npm run build && node -r ts-node/register/transpile-only -r tsconfig-paths/register dist/src
不支持 ts-node
的 files
字段。由于我要添加自定义类型合并,因此需要 tsconfig
,方法是在运行 files
时放置一个 --files
标志。
这里有关于这个主题的资源和灵感:
https://github.com/TypeStrong/ts-node#programmatic