Home > other >  Typescript: Return array of mapped objects based on string[]
Typescript: Return array of mapped objects based on string[]

Time:09-23

I want to create a function that returns the mongo collections i need, based on a string array.

Here is where I am at right now.

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>,
  };
};

And here is how I want to call it:

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

Right now my TS thinks that both userCollection and ordersCollection is a mongodb.Collection<User | Order> where I want it to know that userCollection should be mongodb.Collection<User> and ordersCollection should be mongodb.Collection<Order> based on the string[] I pass to the function.

/Peter

CodePudding user response:

If you replace collectionNames: T with collectionNames: [...T] in the definition of mongo, TypeScript will regard T as a tuple type and infer the correct return type:

const mongo = async <T extends CollectionNames[]>(
  collectionNames: [...T]
): Promise<CollectionAndConn<T>> => {
  ..
}
const {
  conn,
  collections: [usersCollection, ordersCollection],
  // (property) collections: [mongodb.Collection<User>, mongodb.Collection<Order>]
} = await mongo(['users', 'orders']);

TypeScript playground

  • Related