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

如何将TypeScript对象数组映射函数改造为通用泛型函数

泛化实现:数组转指定结构对象的TypeScript方案

针对你提出的三个场景,以下是更简洁、类型安全的泛化实现,解决你遇到的类型错误问题:

基础类型复用

先复用你定义的基础类型,确保所有可映射的资产都符合结构要求:

type NamedAsset = SanityDocument & { id: Slug }; // Slug需包含`current`字符串属性

场景1:仅泛化目标映射类型(Pic类型固定)

最低需求实现,固定输入为Pic数组,仅泛化输出的映射结构:

function mapPicToMap<V extends Record<string, Pic>>(items: Pic[]): V {
  return items.reduce((acc, pic) => {
    const key = pic.id.current as keyof V;
    acc[key] = pic;
    return acc;
  }, {} as V);
}

使用示例

type PicMap = { alpha: Pic; bravo: Pic };
const picMap: PicMap = mapPicToMap(pics);

说明:用Record<string, Pic>约束泛型V,确保输出对象的键为字符串、值为Pic,类型断言仅用于关联业务中已知匹配的键,安全且简洁。


场景2:同时泛化输入类型和目标映射类型

支持任意符合NamedAsset的输入类型,同时泛化输出映射结构:

function mapAssetsToMap<T extends NamedAsset, V extends Record<string, T>>(items: T[]): V {
  return items.reduce((acc, asset) => {
    const key = asset.id.current as keyof V;
    acc[key] = asset;
    return acc;
  }, {} as V);
}

使用示例

// 假设有另一个资产类型
type Video = SanityDocument & { id: Slug; duration: number };
const videos: Video[] = await sanityClient.fetch(`*[_type == "video"]`);

// 定义目标映射类型
type VideoMap = { intro: Video; demo: Video };
const videoMap: VideoMap = mapAssetsToMap(videos);

说明:泛型T约束输入项必须包含id.current,V约束输出结构的类型与输入一致,完全复用且类型安全。


场景3:自动推导映射类型,无需显式定义

无需提前声明映射类型,让TypeScript自动根据数组元素的id.current推导输出结构:

function mapAssetsToAutoMap<T extends NamedAsset>(items: readonly T[]): {
  [K in T['id']['current']]: T extends { id: { current: K } } ? T : never;
} {
  return items.reduce((acc, asset) => {
    acc[asset.id.current as keyof typeof acc] = asset;
    return acc;
  }, {} as any);
}

使用示例

// 假设pics数组的id.current分别为"alpha"和"bravo"
const picMap = mapAssetsToAutoMap(pics);
// 自动推导类型为:{ alpha: Pic; bravo: Pic }
// 直接访问picMap.alpha时,类型自动识别为Pic

说明:利用索引类型和条件类型自动生成键值对,初始值的any仅用于reduce内部,外部返回的类型是严格推导的,无需手动定义映射类型,兼顾便捷性和类型安全。


关于你遇到的类型错误

你之前的泛型函数出现「Type 'K' is not assignable」错误,是因为泛型参数T extends K[]的定义导致类型推导混乱,且V与K之间没有建立有效的类型约束关系。上面的方案通过Record<string, T>明确了输出结构与输入类型的关联,彻底解决了类型不兼容问题。

对比ChatGPT的方案,以上实现更简洁,避免了复杂的Extract语法,同时保持了类型推导的准确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:43:12