如何为Express.js响应动作创建精准的TypeScript类型?
问题:为Express响应动作创建更具体的类型
我希望为使用Express.js的Response对象进行响应的动作创建类型。我发现可以将其标注为Promise<Response>,但该类型不够具体,请问能否在类型中包含User属性以及手动传入json方法的字段?
现有代码
路由代码
import { Router } from "express"; import { sign_up } from "../controllers/users.controller"; import { validateRequest } from "zod-express"; import { UsersSignUpBody } from "../models/users"; export const usersRouter = Router(); usersRouter.post("/sign_up", validateRequest({ body: UsersSignUpBody }), sign_up);
控制器代码
export async function sign_up(req: TypedRequestBody<typeof UsersSignUpBody>, res: Response) { const name = req.body.name; const password = req.body.password; const user = await createUser({name, password}); ///prisma used here return res.json({ attributes: user, dataType: 'user' }); }
解决方案
当然可以创建更具体的类型来约束响应结构,以下是具体实现步骤:
- 定义响应数据结构类型
先明确json方法返回的结构,结合你的User模型(这里假设是Prisma生成的User类型):
import { User } from '@prisma/client'; // 定义响应体的具体类型 type UserResponseData = { attributes: User; dataType: 'user'; };
- 创建自定义Response类型
Express的Response本身是泛型类型,可以传入响应体类型来约束json方法的参数:
import { Response } from 'express'; // 自定义响应类型,指定json方法接收的参数必须符合UserResponseData结构 type UserResponse = Response<UserResponseData>;
- 在控制器中应用自定义类型
修改控制器的res参数类型,同时明确函数返回类型:
import { Response } from 'express'; import { User } from '@prisma/client'; import { TypedRequestBody } from 'zod-express'; import { UsersSignUpBody } from '../models/users'; type UserResponseData = { attributes: User; dataType: 'user'; }; type UserResponse = Response<UserResponseData>; export async function sign_up( req: TypedRequestBody<typeof UsersSignUpBody>, res: UserResponse ): Promise<UserResponse> { const { name, password } = req.body; const user = await createUser({name, password}); return res.json({ attributes: user, dataType: 'user' }); }
这样修改后,res.json会强制要求传入符合UserResponseData结构的参数,函数返回类型也明确为包含指定响应体的Response,比Promise<Response>的约束性强得多。如果需要复用这类响应结构,还可以把类型定义抽离到单独的类型文件中,方便其他控制器调用。
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

