NodeJS 如何将 typescript 定义添加到Express请求和资源

13z8s7eq  于 2023-02-08  发布在  Node.js
关注(0)|答案(6)|浏览(144)

我有一组用于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" />
t30tvxxf

t30tvxxf1#

您可以使用ES6样式命名的imports只导入您需要的接口,而不是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。

rfbsl7qr

rfbsl7qr2#

每次需要编写中间件函数时都要键入参数,这样就可以直接键入整个函数,这可能会让人望而生畏。

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) => {
  ...
};
imzjd6km

imzjd6km3#

我发现可以非常有效地利用TypeScript泛型来创建一个围绕Express Request类型的 Package 器。
您可以在接口文件/文件夹中声明类似于以下内容的内容:

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接口的一个 Package 器,并使用您传递给它的泛型填充它,但也是可选的(注意Record<string, unknown>。然后,它还在每个泛型周围应用Partial(您可能希望将其改为DeepPartial
ExpressMiddleware包含3个可选的泛型ReqBodyResQueryString,它们用于构造类似于中间件/控制器的函数签名。
上面的代码允许您按如下方式进行强类型输入和使用:

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体验带来了巨大的变化。

7d7tgy0s

7d7tgy0s4#

最好的方法是这样做。
//在项目中创建一些共享类型

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) {

   // ....
});
omvjsjqw

omvjsjqw5#

除了安装类型(@types/express),你还应该定义请求参数。因为每个参数都是字符串,接口应该基于字典。
下面是一个内联路由处理程序:

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

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

yhxst69z6#

用途:

req: Express.Request
res: Express.Response

相关问题