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

TypeScript中如何使用泛型函数正确获取嵌套对象的属性值

TS 泛型获取嵌套图标集连字值的正确实现

核心问题

此前的实现未将泛型参数和嵌套对象的层级索引做关联约束,导致 TypeScript 无法匹配入参与返回值的类型对应关系,因此只能推导为联合类型或 undefined。

新方案(支持「图标源/图标名」格式输入)

第一步:定义冻结的图标集常量

使用as const冻结图标集对象,确保 TypeScript 可以提取到具体的字面量类型,而非广义的string:

const ICONS = {
  standard: {
    home: 'icon-home',
    setting: 'icon-setting'
  },
  business: {
    order: 'biz-icon-order',
    customer: 'biz-icon-customer'
  }
} as const

// 提取图标源类型
type IconSource = keyof typeof ICONS
// 提取指定源下的合法图标名类型
type IconName<T extends IconSource> = keyof typeof ICONS[T]

第二步:实现泛型查询函数

使用模板字符串类型绑定入参格式,逐层约束泛型参数的继承关系:

function getIcon<T extends IconSource, K extends IconName<T>>(
  input: `${T}/${K}` | K
): typeof ICONS[T][K] | undefined {
  let source: IconSource = 'standard'
  let iconName: string
  if (typeof input !== 'string') return undefined

  if (input.includes('/')) {
    const [rawSource, rawName] = input.split('/') as [string, string]
    if (!Object.keys(ICONS).includes(rawSource)) return undefined
    source = rawSource as T
    iconName = rawName
  } else {
    iconName = input
  }

  return (ICONS[source] as any)?.[iconName] as typeof ICONS[T][K] | undefined
}

效果验证

// 返回值推导为字面量类型 "icon-home"
const homeIcon = getIcon('home')
// 返回值推导为字面量类型 "biz-icon-order"
const orderIcon = getIcon('business/order')
// 非法入参返回 undefined
const invalidIcon = getIcon('xxx/yyy')

旧方案(enum 定义图标集)

修正泛型约束逻辑

逐层关联图标源和对应图标名的类型约束:

enum IconSource {
  Standard = 'standard',
  Business = 'business'
}

enum StandardIcons {
  Home = 'home',
  Setting = 'setting'
}

enum BusinessIcons {
  Order = 'order',
  Customer = 'customer'
}

interface GlobalIcons {
  [IconSource.Standard]: Record<StandardIcons, string>
  [IconSource.Business]: Record<BusinessIcons, string>
}

const ICONS: GlobalIcons = {
  [IconSource.Standard]: {
    [StandardIcons.Home]: 'icon-home',
    [StandardIcons.Setting]: 'icon-setting'
  },
  [IconSource.Business]: {
    [BusinessIcons.Order]: 'biz-icon-order',
    [BusinessIcons.Customer]: 'biz-icon-customer'
  }
}

function getIcon<T extends IconSource, K extends keyof GlobalIcons[T]>(
  source: T,
  iconName: K
): GlobalIcons[T][K] | undefined {
  return ICONS[source]?.[iconName]
}

// 返回值正确推导为 string 类型
const home = getIcon(IconSource.Standard, StandardIcons.Home)

类型推导正常的核心逻辑

  1. 泛型参数需做层级关联约束,确保第二个泛型参数是第一个泛型参数对应对象的合法键
  2. 常量对象需要用as const冻结,避免 TypeScript 把属性值拓宽为广义的string类型
  3. 字符串格式入参可以用模板字符串类型${T}/${K}和泛型参数做绑定,支持 TypeScript 自动根据输入字面量推导返回值类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:54:01