Skip to content

Commit 78f6e72

Browse files
committed
fix: change result type based on nameOnly option
1 parent c4adb19 commit 78f6e72

File tree

3 files changed

+57
-12
lines changed

3 files changed

+57
-12
lines changed

src/db.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ import {
3434
DropDatabaseOptions,
3535
DropCollectionOptions
3636
} from './operations/drop';
37-
import { ListCollectionsCursor, ListCollectionsOptions } from './operations/list_collections';
37+
import {
38+
CollectionInfo,
39+
ListCollectionsCursor,
40+
ListCollectionsOptions
41+
} from './operations/list_collections';
3842
import { ProfilingLevelOperation, ProfilingLevelOptions } from './operations/profiling_level';
3943
import { RemoveUserOperation, RemoveUserOptions } from './operations/remove_user';
4044
import { RenameOperation, RenameOptions } from './operations/rename';
@@ -358,8 +362,25 @@ export class Db {
358362
* @param filter - Query to filter collections by
359363
* @param options - Optional settings for the command
360364
*/
361-
listCollections(filter?: Document, options?: ListCollectionsOptions): ListCollectionsCursor {
362-
return new ListCollectionsCursor(this, filter ?? {}, resolveOptions(this, options));
365+
listCollections(
366+
filter: Document,
367+
options: Exclude<ListCollectionsOptions, 'nameOnly'> & { nameOnly: true }
368+
): ListCollectionsCursor<Pick<CollectionInfo, 'name' | 'type'>>;
369+
listCollections(
370+
filter: Document,
371+
options: Exclude<ListCollectionsOptions, 'nameOnly'> & { nameOnly: false }
372+
): ListCollectionsCursor<CollectionInfo>;
373+
listCollections<
374+
T extends Pick<CollectionInfo, 'name' | 'type'> | CollectionInfo =
375+
| Pick<CollectionInfo, 'name' | 'type'>
376+
| CollectionInfo
377+
>(filter?: Document, options?: ListCollectionsOptions): ListCollectionsCursor<T>;
378+
listCollections<
379+
T extends Pick<CollectionInfo, 'name' | 'type'> | CollectionInfo =
380+
| Pick<CollectionInfo, 'name' | 'type'>
381+
| CollectionInfo
382+
>(filter: Document = {}, options: ListCollectionsOptions = {}): ListCollectionsCursor<T> {
383+
return new ListCollectionsCursor<T>(this, filter, resolveOptions(this, options));
363384
}
364385

365386
/**

src/operations/list_collections.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export interface CollectionInfo extends Document {
118118

119119
/** @public */
120120
export class ListCollectionsCursor<
121-
T extends string | CollectionInfo = CollectionInfo
121+
T extends Pick<CollectionInfo, 'name' | 'type'> | CollectionInfo = CollectionInfo
122122
> extends AbstractCursor<T> {
123123
parent: Db;
124124
filter: Document;

test/types/list_collections.test-d.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,38 @@ import type { CollectionInfo, ListCollectionsCursor } from '../../src/operations
66
const db = new MongoClient('').db();
77

88
// We default to the CollectionInfo result type
9-
expectType<ListCollectionsCursor<CollectionInfo>>(db.listCollections());
10-
// We do not return the string result, and since its a runtime option there's not a great TS way to capture this
11-
expectNotType<ListCollectionsCursor<string>>(db.listCollections());
9+
expectType<ListCollectionsCursor<Pick<CollectionInfo, 'name' | 'type'> | CollectionInfo>>(
10+
db.listCollections()
11+
);
12+
// By default it isn't narrowed to either type
13+
expectNotType<ListCollectionsCursor<Pick<CollectionInfo, 'name' | 'type'>>>(db.listCollections());
14+
expectNotType<ListCollectionsCursor<CollectionInfo>>(db.listCollections());
15+
16+
// Testings each argument variation
17+
db.listCollections();
18+
db.listCollections({ a: 2 });
19+
db.listCollections({ a: 2 }, { batchSize: 2 });
1220

13-
// toArray is a good way for TS users to keep their code simple
1421
const collections = await db.listCollections().toArray();
15-
expectType<CollectionInfo[]>(collections);
22+
expectType<(CollectionInfo | string)[]>(collections);
23+
24+
const nameOnly = await db.listCollections({}, { nameOnly: true }).toArray();
25+
expectType<Pick<CollectionInfo, 'name' | 'type'>[]>(nameOnly);
26+
27+
const fullInfo = await db.listCollections({}, { nameOnly: false }).toArray();
28+
expectType<CollectionInfo[]>(fullInfo);
29+
30+
const couldBeEither = await db.listCollections({}, { nameOnly: Math.random() > 0.5 }).toArray();
31+
expectType<(CollectionInfo | string)[]>(couldBeEither);
1632

17-
// toArray takes an override so here we can get an array of strings easily
18-
const collectionNames = await db.listCollections({}, { nameOnly: true }).toArray<string>();
19-
expectType<string[]>(collectionNames);
33+
// Showing here that:
34+
// regardless of the option the generic parameter can be used to coerce the result if need be
35+
// note the nameOnly: false, yet strings are returned
36+
const overridden = await db
37+
.listCollections<Pick<CollectionInfo, 'name' | 'type'>>({}, { nameOnly: false })
38+
.toArray();
39+
expectType<Pick<CollectionInfo, 'name' | 'type'>[]>(overridden);
40+
const overriddenWithToArray = await db
41+
.listCollections({}, { nameOnly: false })
42+
.toArray<Pick<CollectionInfo, 'name' | 'type'>>();
43+
expectType<Pick<CollectionInfo, 'name' | 'type'>[]>(overriddenWithToArray);

0 commit comments

Comments
 (0)