使用 TypeScript 和 Express Mergeparams

4

我正在使用Typescript进行我的小项目,但遇到了一个问题。我正在嵌套我的路由器,但Typescript似乎无法识别父级参数。

在“子文件”中,我有以下代码:

const childRouter = express.Router({ mergeParams: true });

childRouter.get('/', (req, res) => {
    const userName = req.params.username; 
    // This causes the error, Property 'username' does not exist on type '{}'
});


然后在“父”文件上的代码是:
import childRouter from './child';

const parentRouter = express.Router();

parentRouter.use('/:username', childRouter);

我不知道如何解决这个问题,似乎Typescript无法识别我正在使用父组件的参数。有没有任何解决办法?


我认为没有简单的解决方法,但您可以更改路由器和父级路径,或完全放弃路由器。 - zenly
回溯到 https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/64437,我正在报告 Express 类型的错误。 - Coderer
5个回答

0

编辑:我第一次阅读帖子时看错了。

如果您已经正确安装了Express的类型,则request.params应该是以下类型。

interface ParamsDictionary {
    [key: string]: string;
}

如果你需要强制类型,你也可以按照以下方式操作:
const username = req.params.username as string

“我不知道Router.use()是否支持params。” 它是支持的,OP的使用情况完全有效。 - robertklep
哦,对了,我刚才误读了帖子,现在再看一遍。 - Pavel

0
我有一个不是很理想但也不错的、多功能的解决方案,考虑到无法了解父级参数的情况。
type parentParam = { username: string };

childRouter.get('/:childId', (req, res) => {
    const { userName, childId } = req.params as typeof req.params & parentParam;
    ...

你可以声明子组件不知道的父组件参数,并在需要时在路由中添加其他子组件参数。 这样做可以保持原生的Express TS类型检查,对于子组件上已存在的参数以及父组件的参数都能进行检查。

0
我到目前为止还没有找到任何“好”的解决方案,但是我做了这个,效果非常不错:
(都是为了类型支持的缘故...)

userid.ts

const userIdRouterConstuctor = (userid: string) => {

  router.get("/", async (req, res, next) => {
    res.send(`User id is now: ${userid}`);
  });

  return router;
};

export default userIdRouterConstuctor;

现在您可以在 users 中创建一个新的路由器,它具有可用的用户ID…

users.ts

router.use("/:userid", (req, res, next) => {
  const { userid } = req.params;
  userIdRouterConstuctor(userid)(req, res, next);
});

0
很遗憾,你无法从实际的父路由中推断出来。
最简洁的方法是使用泛型:
import { RouteParameters } from 'express-serve-static-core';

type WithParentParams<T extends string> = RouteParameters<':userName'> & RouteParameters<T>
//                       Add any other parent params here -^^^^^^^^^

const route = '/' as const;

childRouter.get<typeof route, WithParentParams<typeof route>>(route, async (req, res) => {
  const { userName } = req.params;

这有点复杂,因为你需要设置WithParentParams并将路由重复作为childRouter.get<routeType, paramsType>的第一个参数。
不过,明确一点总比强制类型转换要好。

-1

有点不太优雅的解决方案:

childRouter.get('/', (req, res) => {
  const { username } = req.params as any;
  …
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接