如何将 Typescript 定义添加到 Express req 和 res

Posted

技术标签:

【中文标题】如何将 Typescript 定义添加到 Express req 和 res【英文标题】:How to add Typescript definitions to Express req & res 【发布时间】:2016-04-03 03:53:41 【问题描述】:

我有一组用于我的 REST API 的控制器函数,并且我得到了很多以下内容

error TS7006: Parameter 'req' implicitly has an 'any' type.

res 也是如此。我一直在玩打字等,但没有成功。例如下面的Request 类型参数不起作用。

以下是控制器文件的示例。参考路径正确。

/// <reference path="../../../typings/tsd.d.ts" />    
/* globals require */    
"use strict";    
exports.test = (req : Request, res) => 

我尝试将import * as express from "express"; 添加到文件中 - 我通常不需要它,因为这些函数是由实际实现路由的 index.js 导出和使用的。

这是 tsd.d.ts

/// <reference path="requirejs/require.d.ts" />
/// <reference path="express/express.d.ts" />
/// <reference path="mime/mime.d.ts" />
/// <reference path="node/node.d.ts" />
/// <reference path="serve-static/serve-static.d.ts" />
/// <reference path="bluebird/bluebird.d.ts" />
/// <reference path="mongoose/mongoose.d.ts" />

【问题讨论】:

你试过exports.test = (req: express.Request, res)...吗? 谢谢 - 这似乎有帮助,除了它要求我将 import * as express from "express"; 放入我的控制器中,即使我没有在我的代码中使用它们 ...req: Express.Request.. 怎么样(大写 E,因为它在 tsd 中)? 不,这似乎不起作用。感谢您所做的工作 【参考方案1】:

您可以使用 ES6 风格的命名导入来仅导入您需要的接口,而不是 import * as express from 'express',后者会包含 express 本身。

首先,确保您已安装 express (npm install -D @types/express) 的类型定义。

例子:

// middleware/authCheck.ts
import  Request, Response, NextFunction  from 'express';

export const authCheckMiddleware = (req: Request, res: Response, next: NextFunction) => 
  ...
;

// server.ts
import  authCheckMiddleware  from './middleware/authCheck';
app.use('/api', authCheckMiddleware);

目前使用 TypeScript 2.3.4 和 @types/express 4.0.36。

【讨论】:

你会如何使用 CommonJS 语法来做到这一点【参考方案2】:

最好的办法就是这样。

// 在你的项目中创建一些共享类型

import  Request, Response, NextFunction  from 'express';
export type MiddlewareFn = (req: Request, res: Response, next: NextFunction) => void;

//然后使用上面的类型:

import MiddlewareFn from './my-types.d.ts'

router.get('/foo', <MiddlewareFn>function (req, res, next) 

   // ....
);

【讨论】:

【参考方案3】:

每次您需要编写中间件函数时都输入参数可能会令人生畏,因此您也可以直接输入整个函数。

npm i @types/express --save-dev ("@types/express": "^4.17.0")

安装打字后..

// This can be shortened..
import  Request, Response, NextFunction  from 'express';
export const myMiddleware = (req: Request, res: Response, next: NextFunction) => 
  ...
;

// to this..
import  RequestHandler  from 'express';
export const myMiddleware: RequestHandler = (req, res, next) => 
  ...
;

// or in case it handles the error object
import  ErrorRequestHandler  from 'express';
export const myMiddleware: ErrorRequestHandler = (err, req, res, next) => 
  ...
;

【讨论】:

我正在使用这种方法,需要在使用它的每个文件中导入 Request, Response ,没有办法将其导入一次并使其可用于整个应用程序?【参考方案4】:

除了安装类型(@types/express),您还应该定义请求参数。由于每个参数都是字符串,接口应该基于字典。

这是一个内联路由处理程序:

interface GetParams 
  [key: string]: string
  paramName: string


router.get<GetParams>('/:paramName', (req, res) => 
  res.send('Parameter is ' + req.params.paramName)
)

【讨论】:

它有效,但它非常错误。 paramName 是字符串或未定义...垃圾api和快递方面的类型【参考方案5】:

我发现您可以非常有效地利用 TypeScript 泛型来围绕 Express Request 类型创建包装器。

您可以在接口文件/文件夹中声明类似于此的内容:

import  NextFunction, Request, Response  from 'express';

type TypedRequest<
  ReqBody = Record<string, unknown>,
  QueryString = Record<string, unknown>
> = Request<
  Record<string, unknown>,
  Record<string, unknown>,
  Partial<ReqBody>,
  Partial<QueryString>
>;

export type ExpressMiddleware<
  ReqBody = Record<string, unknown>,
  Res = Record<string, unknown>,
  QueryString = Record<string, unknown>
> = (
  req: TypedRequest<ReqBody, QueryString>,
  res: Response<Res>,
  next: NextFunction
) => Promise<void> | void;

TypedRequest 实际上是 Express 的 Request 接口的包装器,并使用您传递的泛型填充它,但也是可选的(注意 Record&lt;string, unknown&gt;。然后它还会在每个接口周围应用 Partial泛型(您可能希望将其设为 DeepPartial

ExpressMiddleware 接受 3 个可选泛型 ReqBody ResQueryString。这些用于构造类似于中间件/控制器应该是什么样子的函数签名。

然后上面允许你强类型和消费如下:

import  ExpressMiddleware  from '../interfaces/ExpressMiddleware';

type Req =  email: string; password: string ;

type Res =  message: string ;

export const signupUser: ExpressMiddleware<Req, Res> = async (req, res) => 
  /* strongly typed `req.body`. yay autocomplete ? */
  res.json( message: 'you have signed up' ) // strongly typed response obj
;

我希望这对某人有所帮助。这对我的 Express 体验产生了巨大的影响。

【讨论】:

【参考方案6】:

用途:

req: Express.Request
res: Express.Response

【讨论】:

请考虑您还可以扩展 Express 内置类型和接口以获得更大的灵活性

以上是关于如何将 Typescript 定义添加到 Express req 和 res的主要内容,如果未能解决你的问题,请参考以下文章

为啥 TypeScript 将 .default 添加到全局定义的导入中?

将定义添加到 Typescript 中的现有模块

编写自定义指令以将工具提示添加到AngularJS中的ng-options(TypeScript)

如何将 typescript-eslint 规则添加到 eslint

如何将测试添加到现有的 Typescript 项目,并让它显示在测试资源管理器中?

如何将样式化组件作为属性添加到 TypeScript 中的另一个样式化组件?