Skip to content

Commit

Permalink
🤖 Merge PR DefinitelyTyped#49783 Change the definition of Omit<T, K> …
Browse files Browse the repository at this point in the history
…so that it preserves discriminated unions by @ikeyan

* Change the definition of EnhancedOmit so that it preserves discriminated unions

* added a test for discriminated unions

* apply prettier

Co-authored-by: 池下克彦 <[email protected]>
  • Loading branch information
ikeyan and ikeyan authored Dec 5, 2020
1 parent 6c198b5 commit da4523f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 10 deletions.
22 changes: 13 additions & 9 deletions types/mongodb/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ import { EventEmitter } from 'events';
import { Readable, Writable } from 'stream';
import { checkServerIdentity } from 'tls';

// We can use TypeScript Omit once minimum required TypeScript Version is above 3.5
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;

type FlattenIfArray<T> = T extends ReadonlyArray<infer R> ? R : T;

export function connect(uri: string, options?: MongoClientOptions): Promise<MongoClient>;
Expand Down Expand Up @@ -783,7 +780,10 @@ export class Db extends EventEmitter {
collections(callback: MongoCallback<Array<Collection<Default>>>): void;
/** http://mongodb.github.io/node-mongodb-native/3.1/api/Db.html#command */
command(command: object, callback: MongoCallback<any>): void;
command(command: object, options?: { readPreference?: ReadPreferenceOrMode; session?: ClientSession }): Promise<any>;
command(
command: object,
options?: { readPreference?: ReadPreferenceOrMode; session?: ClientSession },
): Promise<any>;
command(
command: object,
options: { readPreference: ReadPreferenceOrMode; session?: ClientSession },
Expand Down Expand Up @@ -1078,10 +1078,12 @@ export interface FSyncOptions extends CommonOptions {
fsync?: boolean;
}

// TypeScript Omit (Exclude to be specific) does not work for objects with an "any" indexed type
// TypeScript Omit (Exclude to be specific) does not work for objects with an "any" indexed type, and breaks discriminated unions
type EnhancedOmit<T, K> = string | number extends keyof T
? T // T has indexed type e.g. { _id: string; [k: string]: any; } or it is "any"
: Omit<T, K>;
: T extends any
? Pick<T, Exclude<keyof T, K>> // discriminated unions
: never;

type ExtractIdType<TSchema> = TSchema extends { _id: infer U } // user has defined a type for _id
? {} extends U
Expand Down Expand Up @@ -2161,8 +2163,8 @@ export interface BulkWriteOpResultObject {
modifiedCount?: number;
deletedCount?: number;
upsertedCount?: number;
insertedIds?: {[index: number]: any};
upsertedIds?: {[index: number]: any};
insertedIds?: { [index: number]: any };
upsertedIds?: { [index: number]: any };
result?: any;
}

Expand Down Expand Up @@ -2733,7 +2735,9 @@ export class AggregationCursor<T = Default> extends Cursor<T> {
/** http://mongodb.github.io/node-mongodb-native/3.1/api/AggregationCursor.html#unshift */
unshift(stream: Buffer | string): void;
/** http://mongodb.github.io/node-mongodb-native/3.1/api/AggregationCursor.html#unwind */
unwind<U = T>(field: string | { path: string; includeArrayIndex?: string; preserveNullAndEmptyArrays?: boolean; }): AggregationCursor<U>;
unwind<U = T>(
field: string | { path: string; includeArrayIndex?: string; preserveNullAndEmptyArrays?: boolean },
): AggregationCursor<U>;
}

/** http://mongodb.github.io/node-mongodb-native/3.1/api/CommandCursor.html#~resultCallback */
Expand Down
17 changes: 16 additions & 1 deletion types/mongodb/test/collection/findX.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async function run() {
readonlyFruitTags: ReadonlyArray<string>;
}
const collectionT = db.collection<TestModel>('testCollection');
collectionT.find({
await collectionT.find({
$and: [{ numberField: { $gt: 0 } }, { numberField: { $lt: 100 } }],
readonlyFruitTags: { $all: ['apple', 'pear'] },
});
Expand All @@ -46,6 +46,21 @@ async function run() {
},
);

// test with discriminated union type
interface DUModelEmpty {
type: 'empty';
}
interface DUModelString {
type: 'string';
value: string;
}
type DUModel = DUModelEmpty | DUModelString;
const collectionDU = db.collection<DUModel>('testDU');
const duValue = await collectionDU.findOne({});
if (duValue && duValue.type === 'string') {
const value: string = duValue.value;
}

// collection.findX<T>() generic tests
interface Bag {
cost: number;
Expand Down

0 comments on commit da4523f

Please sign in to comment.