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)
类型推导正常的核心逻辑
- 泛型参数需做层级关联约束,确保第二个泛型参数是第一个泛型参数对应对象的合法键
- 常量对象需要用
as const冻结,避免 TypeScript 把属性值拓宽为广义的string类型 - 字符串格式入参可以用模板字符串类型
${T}/${K}和泛型参数做绑定,支持 TypeScript 自动根据输入字面量推导返回值类型
内容的提问来源于stack exchange,提问作者michaelT
相关产品推荐
相关产品推荐

