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

基于联合泛型参数条件收窄TypeScript类型的问题

TypeScript泛型类型处理联合角色参数问题

基础类型定义

type UserIsAdmin = // some model
type UserIsVendor = // some model
type UserIsConsumer = // some model

type UserRole = 'admin' | 'vendor' | 'consumer'

type SessionRoles = {
  userIsAdmin: UserIsAdmin | null
  userIsVendor: UserIsVendor | null
  userIsConsumer: UserIsConsumer | null
}

需求

实现泛型类型SessionCheckedRoles<Role extends UserRole>,接收UserRole的单个或联合类型参数,返回过滤后的SessionRoles:

  • 若传入的角色集合包含某类角色,对应字段为该角色的模型类型
  • 否则对应字段为null

原实现及问题

最初的实现代码:

type SessionCheckedRoles<Role extends UserRole> = {
  userIsAdmin: Role extends 'admin' ? UserIsAdmin : null
  userIsVendor: Role extends 'vendor' ? UserIsVendor : null
  userIsConsumer: Role extends 'consumer' ? UserIsConsumer : null
}

单个角色参数时表现正常:

type AdminSessionRoles = SessionCheckedRoles<'admin'>
// 解析结果:
{
  userIsAdmin: UserIsAdmin
  userIsVendor: null
  userIsConsumer: null
}

但传入联合类型时,结果不符合预期:

type VendorConsumerSessionRoles = SessionCheckedRoles<'vendor' | 'consumer'>
// 当前错误解析结果:
{
  userIsAdmin: null
  userIsVendor: UserIsVendor | null
  userIsConsumer: UserIsConsumer | null
}
// 期望的正确结果:
{
  userIsAdmin: null
  userIsVendor: UserIsVendor
  userIsConsumer: UserIsConsumer
}

解决方案

问题根源是分布式条件类型:当泛型参数为联合类型时,Role extends X会自动拆分联合类型的每个成员单独计算,再合并结果,导致字段出现类型 | null的混合值。

修改为反向判断逻辑(检查目标角色是否属于传入的联合类型),即可避免分布式拆分:

type SessionCheckedRoles<Role extends UserRole> = {
  userIsAdmin: 'admin' extends Role ? UserIsAdmin : null
  userIsVendor: 'vendor' extends Role ? UserIsVendor : null
  userIsConsumer: 'consumer' extends Role ? UserIsConsumer : null
}

验证结果

测试联合类型参数:

type VendorConsumerSessionRoles = SessionCheckedRoles<'vendor' | 'consumer'>
// 解析结果符合预期:
{
  userIsAdmin: null
  userIsVendor: UserIsVendor
  userIsConsumer: UserIsConsumer
}

原理说明

'admin' extends Role的逻辑是检查传入的Role类型(无论是否为联合)是否包含'admin',而非拆分Role逐个判断。当Role是'vendor' | 'consumer'时:

  • 'admin' extends Role返回false → userIsAdmin为null
  • 'vendor' extends Role返回true → userIsVendor为UserIsVendor
  • 'consumer' extends Role返回true → userIsConsumer为UserIsConsumer

内容的提问来源于stack exchange,提问作者Cyril CHAPON

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 07:32:55