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

如何实现基于Attribute类型name字段的类型安全对象映射?

问题

现有一个带name属性的泛型类型:

type Attribute<Name, Value> = {
    name : Name
    value : Value
}

关键说明:

  • name参数必须是精确的字符串字面量,比如用Attribute<"width", number>而非Attribute<string, number>;
  • 实际场景中Attribute包含更多属性,这里只保留value简化示例。

需要创建一个映射对象类型,将Attribute["name"]映射到对应的Attribute类型。比如包含Attribute<"width", number>和Attribute<"height", number>的映射对象m,访问m.width时应返回Attribute<"width", number>类型,访问m.height时返回Attribute<"height", number>类型,示例如下:

function f(m : AttributesMap<[
    Attribute<"width", number>,
    Attribute<"height", number>,
]>) {
    m.width.name // 类型应为"width"
    m.height.name // 类型应为"height"
}

尝试了以下写法,但访问m.width和m.height时,返回的都是Attribute<"width", number> | Attribute<"height", number>联合类型:

type AttributesMap<
    Attribute_ extends Attribute<string, any>[]
> = {
    [key in Attribute_[number][`name`]] : Attribute_[number]
}

已知问题出在左右两侧的[number]相互独立,但不知道如何正确实现需求,寻求解决方案。

解决方案

要实现精确的映射,需要利用映射类型结合精确类型提取,核心是让每个键对应到数组中name属性匹配该键的具体Attribute类型。

正确的类型定义如下:

type AttributesMap<T extends Attribute<string, any>[]> = {
    [K in T[number]['name']]: Extract<T[number], { name: K }>
}

原理说明

  • T[number]['name']:提取数组中所有Attribute的name字面量,作为映射的键集合;
  • Extract<T[number], { name: K }>:从数组元素的联合类型中,精确筛选出name属性等于当前键K的那个Attribute类型,确保每个键对应唯一的具体类型,而非整个联合类型。

验证示例

用测试函数验证类型正确性:

function f(m : AttributesMap<[
    Attribute<"width", number>,
    Attribute<"height", number>,
]>) {
    m.width.name // 类型为"width" ✅
    m.height.name // 类型为"height" ✅
    // 访问不存在的键(如m.foo)会直接触发类型错误
}

如果需要支持更灵活的输入(比如直接传入联合类型而非数组),可以调整泛型参数:

type AttributesMap<T extends Attribute<string, any>> = {
    [K in T['name']]: Extract<T, { name: K }>
}

// 使用方式变为传入联合类型
function f(m : AttributesMap<
    Attribute<"width", number> | Attribute<"height", number>
>) {
    m.width.name // "width"
    m.height.name // "height"
}

内容的提问来源于stack exchange,提问作者hopeless-programmer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 13:07:27