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

TypeScript类型折叠导致启用中间件时Body类型丢失的问题求助

TypeScript类型折叠导致启用中间件时Body类型丢失的问题求助

我最近在开发轻量级路由框架的TypeScript类型定义时,遇到了一个非常困惑的问题:当给路由配置添加middleware数组后,请求上下文的body类型会直接丢失,但移除middleware配置后,类型推断又能完全正常工作。

具体现象如下:

  • 同时配置body和middleware时,TypeScript会报错提示ctx.body属性不存在
  • 仅配置body时,ctx.body能被正确推断为对应的业务类型(比如示例中的{ hello: string })

我怀疑这是TypeScript的类型折叠(Type Collapsing)机制导致的,但始终搞不清楚具体触发原因和解决办法。以下是可复现的完整代码:

interface Schema<T> { t: T }
declare const s: Schema<{ hello: string }>

interface BaseContext {
  readonly request: any
}

type Middleware = (context: BaseContext, next: () => Middleware) => any

interface RouteOptions {
  readonly body?: any;
  readonly middleware?: Middleware[];
}

type SpecifyContext<C extends BaseContext, O extends RouteOptions> = 
  { readonly [K in keyof C]: K extends 'request' ? any : C[K] } & 
  (O['body'] extends Schema<infer T> ? { body: T } : {});

type RouteHandler<C extends BaseContext, O extends RouteOptions> = 
  (context: SpecifyContext<C, O>) => any;

class Mini {
  get<const O extends RouteOptions>(
    path: string, 
    handler: RouteHandler<BaseContext, O>, 
    options?: O
  ): Mini {
    return this;
  }
}

const mini = new Mini();

// 此处报错:Property 'body' does not exist on type 'SpecifyContext<BaseContext, { readonly body: Schema<{ hello: string; }>; readonly middleware: [(ctx: BaseContext, next: () => Middleware) => Middleware]; }>'.
mini.get('/example', ctx => ctx.body, 
  { 
    body: s, 
    middleware: [(ctx, next) => next()], 
  } as const, 
);

// 此处完全正常,ctx.body被正确推断为{ hello: string }
mini.get('/example', ctx => ctx.body, 
  { body: s } as const,
);

我观察到的关键类型差异:

  1. 添加middleware时,泛型O被推断为{ readonly body: Schema<{ hello: string; }>; readonly middleware: [(ctx: BaseContext, next: () => Middleware) => Middleware]; },但SpecifyContext的条件类型分支没有被正确触发,没有合并{ body: { hello: string } }的类型
  2. 仅配置body时,泛型O的类型是{ readonly body: Schema<{ hello: string; }>; },SpecifyContext能成功合并业务类型

我尝试过调整交叉结构、修改泛型约束,但都没能解决问题。想请教各位大佬:

  • 这个类型丢失的根本原因是什么?是不是Middleware类型与as const断言的组合触发了TypeScript的类型折叠?
  • 如何修改类型定义,才能让启用middleware时也能正确推断出ctx.body的类型?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 13:02:58