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

TypeScript柯里化函数传入目标对象时如何实现结构类型安全?

问题根源分析

你原来的实现存在两个核心问题:

  • 泛型声明时机错误:你将资源类型泛型T声明在了第一个函数的泛型列表中,但调用第一个函数(传入属性名)时还未传入资源对象,TS无法提前推导T的具体类型,只能默认推导为所有符合{type: ResourceTypes}的联合类型。
  • 全属性类型计算错误:你用keyof Resources[ResourceTypes]['attributes']计算所有属性联合,本质是取所有资源attributes的交集,当不同资源的属性没有重叠时,结果就是never,这就是你新增usergroup后代码直接报错的核心原因。
实现方案

我们只需要调整泛型声明顺序,新增两个工具类型实现属性到资源类型的映射即可:
首先是类型定义部分:

type Resources = {
  user: {
    id: string
    type: 'user'
    attributes: {
      name: string
      age: number
      last_name: string
    }
  },
  usergroup: {
    id: string
    type: 'usergroup'
    attributes: {
      mosterd: string
      group: string
    }
  }
}

type ResourceTypes = keyof Resources

// 分布式遍历所有资源,取所有属性的联合类型
type AllAttributes = {
  [K in ResourceTypes]: keyof Resources[K]['attributes']
}[ResourceTypes]

// 工具类型:根据传入的属性名,反向匹配对应的资源类型
type ResourceByAttribute<A extends AllAttributes> = {
  [K in ResourceTypes]: A extends keyof Resources[K]['attributes'] ? K : never
}[ResourceTypes]

然后是柯里化函数的实现:

function constrain<A extends AllAttributes>(attribute: A) {
  return (resource: Resources[ResourceByAttribute<A>]) => {
    // 业务逻辑示例:返回对应属性值
    return resource.attributes[attribute]
  }
}
效果验证
// 正常调用,类型推导正确
const userName = constrain('name')({
  type: 'user',
  id: '1',
  attributes: { name: '小明', age: 20, last_name: '红' }
})

// 传入错误资源类型时TS会直接报错
const errorCall = constrain('name')({
  type: 'usergroup', // 类型不匹配提示
  id: '2',
  attributes: { mosterd: 'test', group: 'admin' }
})

// 不同资源的属性都能正常校验
const groupKey = constrain('group')({
  type: 'usergroup',
  id: '2',
  attributes: { mosterd: 'test', group: 'admin' }
})

内容的提问来源于stack exchange,提问作者Michiel de Vos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:27:01