You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用泛型简化TypeScript中stackPlayer函数的复杂参数类型?

简化Express中间件栈的TypeScript类型定义

我定义了如下函数:

function stackPlayer(stack){

}

其中stack参数仅允许为以下类型之一:

  • 接收req、res、next作为参数的函数;
  • 接收req、res、next作为参数,且返回同样接收这三个参数的函数的函数;
  • 接收req、res、next作为参数,且返回由上述函数组成的数组的函数;
  • 由上述函数组成的数组。

实际示例:

// 以下均可作为参数传入:
(req, res, next) => {} // 或
(req, res, next) => (req, res, next) => {} // 或
(req,res,sNext) => [(req,res,sNext)=>{}] // 或
[(req,res,sNext)=>{}]

为了给该函数参数添加类型,我编写了如下可读性较差的复杂类型:

type Stack =
  | ((req: Request, res: Response, next: NextFunction) => {})
  | ((
      req: Request,
      res: Response,
      next: NextFunction
    ) => (req: Request, res: Response, next: NextFunction) => {})
  | ((
      req: Request,
      res: Response,
      next: NextFunction
    ) => { (req: Request, res: Response, next: NextFunction): void }[])
  | { (req: Request, res: Response, next: NextFunction): void }[]

function stackPlayer(stack: Stack){

}

我尝试用泛型简化但未成功:

type Smiddleware = <T = void>(req: Request, res: Response, next: NextFunction) => T
type Stack = Smiddleware<void> | Smiddleware<Smiddleware> | Smiddleware<Smiddleware[]> | Smiddleware[]

求可行的简化方案。


解决方案

方案1:拆分基础类型复用

先定义最基础的中间件类型,再基于它扩展出其他需要的类型,结构清晰易读:

import { Request, Response, NextFunction } from 'express';

// 基础中间件:接收req/res/next,返回void
type BaseMiddleware = (req: Request, res: Response, next: NextFunction) => void;

// 返回单个中间件的函数
type MiddlewareReturningMiddleware = (req: Request, res: Response, next: NextFunction) => BaseMiddleware;

// 返回中间件数组的函数
type MiddlewareReturningArray = (req: Request, res: Response, next: NextFunction) => BaseMiddleware[];

// 最终组合的Stack类型
type Stack = BaseMiddleware | MiddlewareReturningMiddleware | MiddlewareReturningArray | BaseMiddleware[];

方案2:泛型类型统一复用

如果你倾向于用泛型实现复用,需要把泛型参数定义在类型别名层面(而非函数层面),修正后的写法如下:

import { Request, Response, NextFunction } from 'express';

// 泛型中间件类型:接收req/res/next,返回指定类型T
type GenericMiddleware<T = void> = (req: Request, res: Response, next: NextFunction) => T;

// 基于泛型组合Stack类型
type Stack = 
  | GenericMiddleware<void> 
  | GenericMiddleware<GenericMiddleware<void>> 
  | GenericMiddleware<GenericMiddleware<void>[]> 
  | GenericMiddleware<void>[];

你之前的泛型写法失效,是因为把Smiddleware定义成了泛型函数类型,而不是接收泛型参数的类型别名。上面的写法将泛型参数绑定到类型别名上,就能正确实现类型复用了。

内容的提问来源于stack exchange,提问作者Islam Y-

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 21:15:41