Skip to content

Commit e68a378

Browse files
authored
Merge pull request #15889 from Automattic/vkarpov15/gh-15878
types(schema): avoid treating paths with default: null as required
2 parents 8e12d23 + 48988be commit e68a378

File tree

5 files changed

+38
-28
lines changed

5 files changed

+38
-28
lines changed

scripts/tsc-diagnostics-check.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
const fs = require('fs');
44

55
const stdin = fs.readFileSync(0).toString('utf8');
6-
const maxInstantiations = isNaN(process.argv[2]) ? 300000 : parseInt(process.argv[2], 10);
6+
const maxInstantiations = isNaN(process.argv[2]) ? 350000 : parseInt(process.argv[2], 10);
77

88
console.log(stdin);
99

test/types/schema.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,3 +1999,20 @@ function autoInferredNestedMaps() {
19991999
const doc = new TestModel({ nestedMap: new Map([['1', new Map([['2', 'value']])]]) });
20002000
expectType<Map<string, Map<string, string>>>(doc.nestedMap);
20012001
}
2002+
2003+
function gh15878() {
2004+
const schema = new Schema({
2005+
name: {
2006+
type: String,
2007+
default: null
2008+
},
2009+
age: {
2010+
type: Number,
2011+
default: () => null
2012+
}
2013+
});
2014+
const TestModel = model('Test', schema);
2015+
const doc = new TestModel({ name: 'John', age: 30 });
2016+
expectType<string | null | undefined>(doc.name);
2017+
expectType<number | null | undefined>(doc.age);
2018+
}

types/inferrawdoctype.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ declare module 'mongoose' {
9797
ResolveRawPathType<Options['of'] extends ReadonlyArray<infer Item> ? Item : never>
9898
: PathValueType extends ArrayConstructor ? any[]
9999
: PathValueType extends typeof Schema.Types.Mixed ? any
100-
: IfEquals<PathValueType, ObjectConstructor> extends true ? any
100+
: PathValueType extends ObjectConstructor ? any
101101
: IfEquals<PathValueType, {}> extends true ? any
102102
: PathValueType extends typeof SchemaType ? PathValueType['prototype']
103103
: PathValueType extends Record<string, any> ? InferRawDocType<PathValueType>

types/inferschematype.d.ts

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,6 @@ declare module 'mongoose' {
127127
: T;
128128
}
129129

130-
type IsPathDefaultUndefined<PathType> =
131-
PathType extends { default: undefined } ? true
132-
: PathType extends { default: (...args: any[]) => undefined } ? true
133-
: false;
134-
135130
type RequiredPropertyDefinition =
136131
| {
137132
required: true | string | [true, string | undefined] | { isRequired: true };
@@ -150,16 +145,17 @@ type IsPathRequired<P, TypeKey extends string = DefaultTypeKey> =
150145
P extends { required: false } ?
151146
false
152147
: true
153-
: P extends Record<TypeKey, ArrayConstructor | any[]> ?
154-
IsPathDefaultUndefined<P> extends true ?
155-
false
156-
: true
157-
: P extends Record<TypeKey, any> ?
158-
P extends { default: any } ?
159-
IfEquals<P['default'], undefined, false, true>
160-
: false
148+
: P extends { default: undefined | null | ((...args: any[]) => undefined) | ((...args: any[]) => null) } ? false
149+
: P extends { default: any } ? true
150+
: P extends Record<TypeKey, ArrayConstructor | any[]> ? true
161151
: false;
162152

153+
// Internal type used to efficiently check for never or any types
154+
// can be efficiently checked like:
155+
// `[T] extends [neverOrAny] ? T : ...`
156+
// to avoid edge cases
157+
type neverOrAny = ' ~neverOrAny~';
158+
163159
/**
164160
* @summary A Utility to obtain schema's required path keys.
165161
* @param {T} T A generic refers to document definition.
@@ -238,6 +234,7 @@ type PathEnumOrString<T extends SchemaTypeOptions<string>['enum']> =
238234

239235
type IsSchemaTypeFromBuiltinClass<T> =
240236
T extends typeof String ? true
237+
: unknown extends Buffer ? false
241238
: T extends typeof Number ? true
242239
: T extends typeof Boolean ? true
243240
: T extends typeof Buffer ? true
@@ -254,7 +251,6 @@ type IsSchemaTypeFromBuiltinClass<T> =
254251
: T extends Types.Decimal128 ? true
255252
: T extends NativeDate ? true
256253
: T extends typeof Schema.Types.Mixed ? true
257-
: unknown extends Buffer ? false
258254
: T extends Buffer ? true
259255
: false;
260256

@@ -270,12 +266,10 @@ type ResolvePathType<
270266
Options extends SchemaTypeOptions<PathValueType> = {},
271267
TypeKey extends string = DefaultSchemaOptions['typeKey'],
272268
TypeHint = never
273-
> = IfEquals<
274-
TypeHint,
275-
never,
276-
PathValueType extends Schema ? InferSchemaType<PathValueType>
269+
> = [TypeHint] extends [never]
270+
? PathValueType extends Schema ? InferSchemaType<PathValueType>
277271
: PathValueType extends AnyArray<infer Item> ?
278-
IfEquals<Item, never> extends true
272+
[Item] extends [never]
279273
? any[]
280274
: Item extends Schema ?
281275
// If Item is a schema, infer its type.
@@ -314,7 +308,7 @@ type ResolvePathType<
314308
: never
315309
: PathValueType extends ArrayConstructor ? any[]
316310
: PathValueType extends typeof Schema.Types.Mixed ? any
317-
: IfEquals<PathValueType, ObjectConstructor> extends true ? any
311+
: PathValueType extends ObjectConstructor ? any
318312
: IfEquals<PathValueType, {}> extends true ? any
319313
: PathValueType extends typeof SchemaType ? PathValueType['prototype']
320314
: PathValueType extends Record<string, any> ?
@@ -325,6 +319,5 @@ type ResolvePathType<
325319
typeKey: TypeKey;
326320
}
327321
>
328-
: unknown,
329-
TypeHint
330-
>;
322+
: unknown
323+
: TypeHint;

types/virtuals.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ declare module 'mongoose' {
88
type TVirtualPathFN<DocType = {}, PathType = unknown, TInstanceMethods = {}, TReturn = unknown> =
99
<T = HydratedDocument<DocType, TInstanceMethods>>(this: Document<any, any, DocType> & DocType, value: PathType, virtual: VirtualType<T>, doc: Document<any, any, DocType> & DocType) => TReturn;
1010

11-
type SchemaOptionsVirtualsPropertyType<DocType = any, VirtualPaths = Record<any, unknown>, TInstanceMethods = {}> = {
12-
[K in keyof VirtualPaths]: VirtualPathFunctions<IsItRecordAndNotAny<DocType> extends true ? DocType : any, VirtualPaths[K], TInstanceMethods>
13-
};
11+
type SchemaOptionsVirtualsPropertyType<DocType = any, VirtualPaths = Record<any, unknown>, TInstanceMethods = {}> = {
12+
[K in keyof VirtualPaths]: VirtualPathFunctions<IsItRecordAndNotAny<DocType> extends true ? DocType : any, VirtualPaths[K], TInstanceMethods>
13+
};
1414
}

0 commit comments

Comments
 (0)