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

TypeScript泛型推断映射类型使用extends的校验异常问题

TypeScript 嵌套泛型类型推导失效问题

问题复现

以下是问题代码及相关Playground链接:

type SomeType<T> = {
  [K in keyof T]?: K extends 'u'
    ? string
    : T[K] extends object
      ? SomeType<T[K]>
      : object
}

function someType<T>(t: SomeType<T>) {
  return t;
}

type BLA = SomeType<{
  u: 1,
  b: {
    u: 1,
  },
}>;

const blaBLA: BLA = {
  u: 1, // <-- 正确报错:Type 'number' is not assignable to type 'string'.
  b: {
    u: 1, // <-- 正确报错:Type 'number' is not assignable to type 'string'.
  },
};

const bla = someType({
  u: 1, // <-- 正确报错:Type 'number' is not assignable to type 'string'.
  b: {
    u: 1, // <-- 预期出现上述相同报错
          // 实际b属性的值被解析为'object'类型,而非'SomeType<T[K]>'
  },
});

异常表现:

  • 显式标注BLA类型的变量blaBLA,两层u字段赋值数字1都能正确触发类型报错
  • 直接调用someType传入对象字面量时,仅顶层u字段会报错,嵌套在b属性下的u字段没有触发类型校验

原理说明

该现象是TypeScript泛型反向推导的性能优化截断机制导致的:

  1. 显式标注类型时,TS会完整展开目标类型,递归校验所有嵌套字段的约束,因此不会出现校验遗漏。
  2. 通过someType<T>(t: SomeType<T>)这种写法调用函数时,TS需要从传入的参数t反向推导泛型参数T。为了控制编译时长,TS在推导嵌套层级的条件类型时,遇到宽泛的object类型匹配会直接命中分支,停止向内层递归展开映射类型。
  3. 由于{u:1}本身是合法的object类型值,命中分支后TS不会再校验对象内部的字段规则,最终导致嵌套层的u字段没有触发类型检查。

修复方案

调整函数的泛型约束逻辑,避免反向推导时的递归截断:

type SomeType<T> = {
  [K in keyof T]?: K extends 'u'
    ? string
    : T[K] extends object
      ? SomeType<T[K]>
      : object
}

// 修改泛型约束:直接推导参数类型为T,再校验T满足SomeType<T>的递归规则
function someType<T extends SomeType<T>>(t: T) {
  return t;
}

修复后逻辑:

  • TS会直接将传入的对象字面量类型推导为泛型T,不需要从SomeType<T>反向推导T
  • 推导完成后TS会递归校验T是否满足SomeType<T>的所有层级约束,嵌套层的b.u字段就会正确抛出类型错误,和显式标注类型的表现完全一致。

内容的提问来源于stack exchange,提问作者Page not found

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 18:45:39