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

TypeScript:根据字符串数组返回对应类型MongoDB集合数组的问题

问题

我希望创建一个函数,根据传入的字符串数组返回所需的MongoDB集合。目前我的实现代码如下:

type CollectionNames = 'users' | 'orders';

type CollectionMap = {
  users: User;
  orders: Order;
};

type CollectionsArray<T extends CollectionNames[]> = {
  [K in keyof T]: mongodb.Collection<CollectionMap[T[K]]>;
};

type CollectionAndConn<T extends CollectionNames[]> = {
  conn: mongodb.MongoClient;
  collections: CollectionsArray<T>; //mongodb.Collection<CollectionMap[T]>[];
};

export const mongo = async <T extends CollectionNames[]>(collectionNames: T): Promise<CollectionAndConn<T>> => {
  const conn = await MongoClient.connect(`${MONGO_URL}`, {});

  return {
    conn,
    collections: collectionNames.map((collectionName) => conn.db().collection(collectionName)) as CollectionsArray<T>,
  };
};

我期望按如下方式调用该函数:

const {
  conn,
  collections: [usersCollection, ordersCollection],
} = await mongo(['users', 'orders']);

但当前TypeScript会将usersCollection和ordersCollection都推断为mongodb.Collection<User | Order>,而我需要它根据传入的字符串数组,正确识别usersCollection为mongodb.Collection<User>,ordersCollection为mongodb.Collection<Order>。

解决方案

问题核心是TypeScript默认会把['users', 'orders']推断为CollectionNames[](元素为联合类型的普通数组),而非保留每个元素具体类型的元组。要实现精准类型推断,需做以下调整:

1. 调整泛型约束为只读元组

修改函数的泛型参数,让T约束为readonly CollectionNames[],这样TypeScript能更好地识别元组类型:

export const mongo = async <T extends readonly CollectionNames[]>(collectionNames: T): Promise<CollectionAndConn<T>> => {
  const conn = await MongoClient.connect(`${MONGO_URL}`, {});

  return {
    conn,
    collections: collectionNames.map((collectionName) => conn.db().collection(collectionName)) as CollectionsArray<T>,
  };
};

2. 调用参数添加const断言

调用函数时,给数组加上as const,强制TypeScript将其推断为只读元组,保留每个元素的具体类型:

const {
  conn,
  collections: [usersCollection, ordersCollection],
} = await mongo(['users', 'orders'] as const);

优化类型定义(可选)

为了避免潜在的类型歧义,可以优化CollectionsArray的定义,用Extract确保元素类型被正确缩小:

type CollectionsArray<T extends readonly CollectionNames[]> = {
  [K in keyof T]: mongodb.Collection<CollectionMap[Extract<T[K], CollectionNames>]>;
};

完成以上修改后,TypeScript就能精准推断:

  • usersCollection 类型为 mongodb.Collection<User>
  • ordersCollection 类型为 mongodb.Collection<Order>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 13:56:41