如何将Typescript定义添加到Express req&水库

时间:2015-12-29 09:22:34

标签: node.js express typescript

我的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" />

5 个答案:

答案 0 :(得分:7)

您可以使用名为import的ES6样式仅导入所需的接口,而不是import * as express from '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。

我有同样的问题,所以我想我会提供一个答案,万一其他人遇到这个问题。

答案 1 :(得分:2)

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

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

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

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

答案 2 :(得分:0)

最好的方法就是这样。

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

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 :(得分:0)

每次需要编写中间件函数时都很难键入参数,因此也可以直接键入整个函数。

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

答案 4 :(得分:0)

我发现您可以非常有效地利用 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<string, unknown>。然后它也应用了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 体验产生了巨大影响。