Skip to content

Commit 259cc7f

Browse files
authored
Merge pull request #11947 from Automattic/6.4
6.4
2 parents 4e7e6ca + 40fef4a commit 259cc7f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+5043
-312
lines changed

.eslintrc.json

+61-34
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,70 @@
44
],
55
"ignorePatterns": [
66
"docs",
7+
"tools",
78
"dist",
8-
"test/files/*"
9+
"website.js",
10+
"test/files/*",
11+
"benchmarks"
912
],
10-
"overrides": [{
11-
"files": [
12-
"**/*.{ts,tsx}"
13-
],
14-
"extends": [
15-
"plugin:@typescript-eslint/eslint-recommended",
16-
"plugin:@typescript-eslint/recommended"
17-
],
18-
"plugins": [
19-
"@typescript-eslint"
20-
],
21-
"rules": {
22-
"@typescript-eslint/triple-slash-reference": "off",
23-
"spaced-comment": ["error", "always", {
24-
"markers": ["/"]
25-
}],
26-
"@typescript-eslint/no-explicit-any": "off",
27-
"@typescript-eslint/ban-types": "off",
28-
"@typescript-eslint/no-unused-vars": "off",
29-
"@typescript-eslint/explicit-module-boundary-types": "off",
30-
"@typescript-eslint/indent": ["error", 2, {
31-
"SwitchCase": 1
32-
}],
33-
"@typescript-eslint/prefer-optional-chain": "error",
34-
"@typescript-eslint/brace-style": "error",
35-
"@typescript-eslint/no-dupe-class-members": "error",
36-
"@typescript-eslint/no-redeclare": "error",
37-
"@typescript-eslint/type-annotation-spacing": "error",
38-
"@typescript-eslint/object-curly-spacing": ["error", "always"],
39-
"@typescript-eslint/semi": "error",
40-
"@typescript-eslint/space-before-function-paren": ["error", "never"],
41-
"@typescript-eslint/space-infix-ops": "off"
13+
"overrides": [
14+
{
15+
"files": [
16+
"**/*.{ts,tsx}"
17+
],
18+
"extends": [
19+
"plugin:@typescript-eslint/eslint-recommended",
20+
"plugin:@typescript-eslint/recommended"
21+
],
22+
"plugins": [
23+
"@typescript-eslint"
24+
],
25+
"rules": {
26+
"@typescript-eslint/triple-slash-reference": "off",
27+
"spaced-comment": [
28+
"error",
29+
"always",
30+
{
31+
"block": {
32+
"markers": [
33+
"!"
34+
],
35+
"balanced": true
36+
},
37+
"markers": [
38+
"/"
39+
]
40+
}
41+
],
42+
"@typescript-eslint/no-explicit-any": "off",
43+
"@typescript-eslint/ban-types": "off",
44+
"@typescript-eslint/no-unused-vars": "off",
45+
"@typescript-eslint/explicit-module-boundary-types": "off",
46+
"@typescript-eslint/indent": [
47+
"error",
48+
2,
49+
{
50+
"SwitchCase": 1
51+
}
52+
],
53+
"@typescript-eslint/prefer-optional-chain": "error",
54+
"@typescript-eslint/brace-style": "error",
55+
"@typescript-eslint/no-dupe-class-members": "error",
56+
"@typescript-eslint/no-redeclare": "error",
57+
"@typescript-eslint/type-annotation-spacing": "error",
58+
"@typescript-eslint/object-curly-spacing": [
59+
"error",
60+
"always"
61+
],
62+
"@typescript-eslint/semi": "error",
63+
"@typescript-eslint/space-before-function-paren": [
64+
"error",
65+
"never"
66+
],
67+
"@typescript-eslint/space-infix-ops": "off"
68+
}
4269
}
43-
}],
70+
],
4471
"plugins": [
4572
"mocha-no-only"
4673
],

docs/guide.md

+44-4
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,18 @@ We may also define our own custom document instance methods.
143143

144144
```javascript
145145
// define a schema
146-
const animalSchema = new Schema({ name: String, type: String });
146+
const animalSchema = new Schema({ name: String, type: String },
147+
{
148+
// Assign a function to the "methods" object of our animalSchema through schema options.
149+
// By following this approach, there is no need to create a separate TS type to define the type of the instance functions.
150+
methods:{
151+
findSimilarTypes(cb){
152+
return mongoose.model('Animal').find({ type: this.type }, cb);
153+
}
154+
}
155+
});
147156

148-
// assign a function to the "methods" object of our animalSchema
157+
// Or, assign a function to the "methods" object of our animalSchema
149158
animalSchema.methods.findSimilarTypes = function(cb) {
150159
return mongoose.model('Animal').find({ type: this.type }, cb);
151160
};
@@ -169,14 +178,28 @@ dog.findSimilarTypes((err, dogs) => {
169178

170179
<h3 id="statics"><a href="#statics">Statics</a></h3>
171180

172-
You can also add static functions to your model. There are two equivalent
181+
You can also add static functions to your model. There are three equivalent
173182
ways to add a static:
174183

184+
- Add a function property to the second argument of the schema-constructor (`statics`)
175185
- Add a function property to `schema.statics`
176186
- Call the [`Schema#static()` function](/docs/api.html#schema_Schema-static)
177187

178188
```javascript
179-
// Assign a function to the "statics" object of our animalSchema
189+
190+
// define a schema
191+
const animalSchema = new Schema({ name: String, type: String },
192+
{
193+
// Assign a function to the "statics" object of our animalSchema through schema options.
194+
// By following this approach, there is no need to create a separate TS type to define the type of the statics functions.
195+
statics:{
196+
findByName(name){
197+
return this.find({ name: new RegExp(name, 'i') });
198+
}
199+
}
200+
});
201+
202+
// Or, Assign a function to the "statics" object of our animalSchema
180203
animalSchema.statics.findByName = function(name) {
181204
return this.find({ name: new RegExp(name, 'i') });
182205
};
@@ -197,6 +220,20 @@ but for mongoose queries. Query helper methods let you extend mongoose's
197220
[chainable query builder API](./queries.html).
198221

199222
```javascript
223+
224+
// define a schema
225+
const animalSchema = new Schema({ name: String, type: String },
226+
{
227+
// Assign a function to the "query" object of our animalSchema through schema options.
228+
// By following this approach, there is no need to create a separate TS type to define the type of the query functions.
229+
query:{
230+
byName(name){
231+
return this.where({ name: new RegExp(name, 'i') })
232+
}
233+
}
234+
});
235+
236+
// Or, Assign a function to the "query" object of our animalSchema
200237
animalSchema.query.byName = function(name) {
201238
return this.where({ name: new RegExp(name, 'i') })
202239
};
@@ -409,6 +446,7 @@ Valid options:
409446
- [read](#read)
410447
- [writeConcern](#writeConcern)
411448
- [shardKey](#shardKey)
449+
- [statics](#statics)
412450
- [strict](#strict)
413451
- [strictQuery](#strictQuery)
414452
- [toJSON](#toJSON)
@@ -423,6 +461,8 @@ Valid options:
423461
- [skipVersioning](#skipVersioning)
424462
- [timestamps](#timestamps)
425463
- [storeSubdocValidationError](#storeSubdocValidationError)
464+
- [methods](#methods)
465+
- [query](#query-helpers)
426466

427467
<h3 id="autoIndex"><a href="#autoIndex">option: autoIndex</a></h3>
428468

docs/typescript/query-helpers.md

+32-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ var Project = mongoose.model('Project', ProjectSchema);
1414
Project.find().where('stars').gt(1000).byName('mongoose');
1515
```
1616

17-
In TypeScript, Mongoose's `Model` takes 3 generic parameters:
17+
In TypeScript, Mongoose does support manually typed and automatically typed Query Helpers.
18+
19+
1- Manually typed:
20+
Mongoose's `Model` takes 3 generic parameters:
1821

1922
1. The `DocType`
2023
2. a `TQueryHelpers` type
@@ -58,4 +61,32 @@ async function run(): Promise<void> {
5861
// Equivalent to `ProjectModel.find({ stars: { $gt: 1000 }, name: 'mongoose' })`
5962
await ProjectModel.find().where('stars').gt(1000).byName('mongoose');
6063
}
64+
```
65+
66+
2- Automatically typed:
67+
Mongoose does support auto typed Query Helpers that it are supplied in schema options.
68+
Query Helpers functions can be defined as following:
69+
70+
```typescript
71+
import { Schema, model } from 'mongoose';
72+
73+
const schema = new Schema({
74+
name: { type: String, required: true },
75+
stars: { type: Number, required: true }
76+
}, {
77+
query: {
78+
byName(name) {
79+
return this.find({ name: name });
80+
}
81+
}
82+
});
83+
84+
const ProjectModel = model(
85+
'Project',
86+
schema
87+
);
88+
89+
// Equivalent to `ProjectModel.find({ stars: { $gt: 1000 }, name: 'mongoose' })`
90+
await ProjectModel.find().where('stars').gt(1000).byName('mongoose');
91+
}
6192
```

docs/typescript/schemas.md

+42-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
# Schemas in TypeScript
22

33
Mongoose [schemas](/docs/guide.html) are how you tell Mongoose what your documents look like.
4-
Mongoose schemas are separate from TypeScript interfaces, so you need to define both a _document interface_ and a _schema_.
4+
Mongoose schemas are separate from TypeScript interfaces, so you need to define both a _document interface_ and a _schema_ until V6.3.1.
5+
Mongoose supports auto typed schemas so you don't need to define additional typescript interface anymore but you are still able to do so.
6+
Mongoose provides a `InferSchemaType`, which infers the type of the auto typed schema document when needed.
7+
8+
`Until mongoose V6.3.1:`
59

610
```typescript
711
import { Schema } from 'mongoose';
@@ -21,6 +25,37 @@ const schema = new Schema<User>({
2125
});
2226
```
2327

28+
`another approach:`
29+
30+
```typescript
31+
import { Schema, InferSchemaType } from 'mongoose';
32+
33+
// Document interface
34+
// No need to define TS interface any more.
35+
// interface User {
36+
// name: string;
37+
// email: string;
38+
// avatar?: string;
39+
// }
40+
41+
// Schema
42+
const schema = new Schema({
43+
name: { type: String, required: true },
44+
email: { type: String, required: true },
45+
avatar: String
46+
});
47+
48+
type User = InferSchemaType<typeof schema>;
49+
// InferSchemaType will determine the type as follows:
50+
// type User = {
51+
// name: string;
52+
// email: string;
53+
// avatar?: string;
54+
// }
55+
56+
57+
```
58+
2459
By default, Mongoose does **not** check if your document interface lines up with your schema.
2560
For example, the above code won't throw an error if `email` is optional in the document interface, but `required` in `schema`.
2661

@@ -51,7 +86,7 @@ Mongoose wraps `DocType` in a Mongoose document for cases like the `this` parame
5186
For example:
5287

5388
```typescript
54-
schema.pre('save', function(): void {
89+
schema.pre('save', function (): void {
5590
console.log(this.name); // TypeScript knows that `this` is a `mongoose.Document & User` by default
5691
});
5792
```
@@ -102,7 +137,7 @@ interface User {
102137
const schema = new Schema<User, Model<User>>({
103138
name: { type: String, required: true },
104139
email: { type: String, required: true },
105-
avatar: String
140+
avatar: String,
106141
});
107142
```
108143

@@ -121,13 +156,13 @@ interface BlogPost {
121156
}
122157

123158
interface User {
124-
tags: Types.Array<string>,
125-
blogPosts: Types.DocumentArray<BlogPost>
159+
tags: Types.Array<string>;
160+
blogPosts: Types.DocumentArray<BlogPost>;
126161
}
127162

128163
const schema = new Schema<User, Model<User>>({
129164
tags: [String],
130-
blogPosts: [{ title: String }]
165+
blogPosts: [{ title: String }],
131166
});
132167
```
133168

@@ -139,4 +174,4 @@ If you use `Types.DocumentArray` in the above case, you'll be able to `push()` a
139174
const user = new User({ blogPosts: [] });
140175

141176
user.blogPosts.push({ title: 'test' }); // Would not work if you did `blogPosts: BlogPost[]`
142-
```
177+
```

docs/typescript/statics-and-methods.md

+21
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,27 @@ const User = model<IUser, UserModel>('User', schema);
6565
const answer: number = User.myStaticMethod(); // 42
6666
```
6767

68+
Mongoose does support auto typed static functions now that it is supplied in schema options.
69+
Statics functions can be defined as following:
70+
71+
```typescript
72+
import { Schema, model } from 'mongoose';
73+
74+
const schema = new Schema(
75+
{ name: String },
76+
{
77+
statics: {
78+
myStaticMethod() {
79+
return 42;
80+
},
81+
},
82+
}
83+
);
84+
85+
const User = model('User', schema);
86+
87+
const answer = User.myStaticMethod(); // 42
88+
```
6889
## Both Methods and Statics
6990

7091
Below is how you can define a model that has both methods and statics.

0 commit comments

Comments
 (0)