Skip to content

Commit 6f52dcb

Browse files
authored
Merge pull request #15577 from Automattic/vkarpov15/gh-12807
types: remove logic that omits timestamps when virtuals, methods, etc. options set
2 parents 509d39d + 68716d6 commit 6f52dcb

File tree

3 files changed

+9
-10
lines changed

3 files changed

+9
-10
lines changed

docs/typescript/schemas.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ There are a few caveats for using automatic type inference:
3030

3131
1. You need to set `strictNullChecks: true` or `strict: true` in your `tsconfig.json`. Or, if you're setting flags at the command line, `--strictNullChecks` or `--strict`. There are [known issues](https://github.com/Automattic/mongoose/issues/12420) with automatic type inference with strict mode disabled.
3232
2. You need to define your schema in the `new Schema()` call. Don't assign your schema definition to a temporary variable. Doing something like `const schemaDefinition = { name: String }; const schema = new Schema(schemaDefinition);` will not work.
33-
3. Mongoose adds `createdAt` and `updatedAt` to your schema if you specify the `timestamps` option in your schema, *except* if you also specify `methods`, `virtuals`, or `statics`. There is a [known issue](https://github.com/Automattic/mongoose/issues/12807) with type inference with timestamps and methods/virtuals/statics options. If you use methods, virtuals, and statics, you're responsible for adding `createdAt` and `updatedAt` to your schema definition.
33+
3. Mongoose adds `createdAt` and `updatedAt` to your schema if you specify the `timestamps` option in your schema.
3434

3535
If you must define your schema separately, use [as const](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) (`const schemaDefinition = { ... } as const;`) to prevent *type widening*. TypeScript will automatically widen types like `required: false` to `required: boolean`, which will cause Mongoose to assume the field is required. Using `as const` forces TypeScript to retain these types.
3636

test/types/schema.test.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -899,11 +899,13 @@ function testInferTimestamps() {
899899
});
900900

901901
type WithTimestamps2 = InferSchemaType<typeof schema2>;
902-
// For some reason, expectType<{ createdAt: Date, updatedAt: Date, name?: string }> throws
903-
// an error "Parameter type { createdAt: Date; updatedAt: Date; name?: string | undefined; }
904-
// is not identical to argument type { createdAt: NativeDate; updatedAt: NativeDate; } &
905-
// { name?: string | undefined; }"
906-
expectType<{ name?: string | null }>({} as WithTimestamps2);
902+
expectType<{ createdAt: Date; updatedAt: Date } & { name?: string | null }>({} as WithTimestamps2);
903+
904+
const TestModel = model('Test', schema2);
905+
const doc = new TestModel({ name: 'test' });
906+
expectType<string | undefined | null>(doc.name);
907+
908+
expectType<string | undefined | null>(doc.myName());
907909
}
908910

909911
function gh12431() {

types/inferschematype.d.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,7 @@ declare module 'mongoose' {
7575

7676
type ApplySchemaOptions<T, O = DefaultSchemaOptions> = ResolveTimestamps<T, O>;
7777

78-
type ResolveTimestamps<T, O> = O extends { methods: any } | { statics: any } | { virtuals: any } | { timestamps?: false } ? T
79-
// For some reason, TypeScript sets all the document properties to unknown
80-
// if we use methods, statics, or virtuals. So avoid inferring timestamps
81-
// if any of these are set for now. See gh-12807
78+
type ResolveTimestamps<T, O> = O extends { timestamps?: false } ? T
8279
: O extends { timestamps: infer TimestampOptions } ? TimestampOptions extends true
8380
? { createdAt: NativeDate; updatedAt: NativeDate; } & T
8481
: TimestampOptions extends SchemaTimestampsConfig

0 commit comments

Comments
 (0)