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

如何从TypeScript泛型Hook中获取特定类型?

问题

我正尝试创建一个连接Firebase/Firestore的泛型Hook,用于返回指定集合的所有数据项。我通过创建ICollectionMap接口来指定各集合数据的类型,现有代码如下:

export const useCollection = <TCollectionMap extends Record<string, any>>(
  collectionName: keyof TCollectionMap
): {
  collection: TCollectionMap[keyof TCollectionMap]
} => {
  const [collection, setCollection] = useState<TCollectionMap[keyof TCollectionMap]>([])

  useEffect(() => {
    // fetch data from Firebase here
    ...
    const data = ...
    setCollection(data)
  }, [])

  return { collection }
}

定义以下类型:

interface INames { name: string }

interface IAges { age: number }

interface ICollectionMap {
  names: INames[]
  ages: IAges[]
}

当我调用该Hook时:

const { collection } = useCollection<ICollectionMap>('names')

我期望collection的类型为INames[],但TypeScript显示其类型为INames[] | IAges[]。请问如何用TypeScript正确处理这个问题?

解决方案

问题核心是当前泛型仅约束了集合映射的整体类型,未将传入的collectionName与返回的集合类型做精准关联。通过新增一个泛型参数锁定具体集合键,即可让TypeScript推导出对应类型:

修改后的Hook代码:

import { useState, useEffect } from 'react';

export const useCollection = <
  TCollectionMap extends Record<string, any>,
  TKey extends keyof TCollectionMap
>(
  collectionName: TKey
): {
  collection: TCollectionMap[TKey]
} => {
  const [collection, setCollection] = useState<TCollectionMap[TKey]>([] as TCollectionMap[TKey])

  useEffect(() => {
    // 示例:模拟Firebase数据请求
    const fetchData = async () => {
      // 实际项目替换为Firestore集合查询逻辑
      const snapshot = await fetch(`/api/${collectionName}`);
      const data = await snapshot.json();
      setCollection(data);
    };

    fetchData();
  }, [collectionName])

  return { collection }
}

调用时的类型推导完全符合预期:

// 手动指定泛型参数的写法
const { collection } = useCollection<ICollectionMap, 'names'>('names');
// collection类型为INames[]

// TypeScript可自动推导TKey参数,无需手动指定
const { collection } = useCollection<ICollectionMap>('names');
// 同样得到INames[]类型

关键改动说明

  • 新增泛型参数TKey extends keyof TCollectionMap,明确绑定传入的集合名称对应的键类型
  • 返回类型与useState泛型均改为TCollectionMap[TKey],让TypeScript精准关联集合名与对应数据类型
  • 初始值通过[] as TCollectionMap[TKey]做类型断言,避免空数组的类型不匹配问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:52:52