UNPKG

5.15 kBMarkdownView Raw
1# Typegoose
2
3<sub>(These badges are from typegoose:master)</sub>
4[![Node.js Tests](https://github.com/typegoose/typegoose/workflows/Node.js%20Tests/badge.svg?branch=master)](https://github.com/typegoose/typegoose/actions?query=workflow%3A"Node.js+Tests")
5[![codecov.io](https://codecov.io/github/typegoose/typegoose/coverage.svg?branch=master)](https://codecov.io/github/typegoose/typegoose?branch=master)
6[![npm](https://img.shields.io/npm/dt/@typegoose/typegoose.svg)](https://www.npmjs.com/package/@typegoose/typegoose)
7
8Define Mongoose models using TypeScript classes
9
10## Migration
11
12Migration Guides:
13(Date format: `dd-mm-yyyy`)
14
15- [8 to 9](https://typegoose.github.io/typegoose/docs/guides/migration/migrate-9) (released on `22-09-2021`)
16- [7 to 8](https://typegoose.github.io/typegoose/docs/guides/migration/migrate-8) (released on `28-07-2021`)
17- [6 to 7](https://typegoose.github.io/typegoose/docs/guides/migration/migrate-7) (released on `01-04-2020`)
18- [5 to 6](https://typegoose.github.io/typegoose/docs/guides/migration/migrate-6) (released on `30-09-2019`)
19
20## Basic usage
21
22```ts
23import { prop, getModelForClass } from '@typegoose/typegoose';
24import * as mongoose from 'mongoose';
25
26class User {
27 @prop()
28 public name?: string;
29
30 @prop({ type: () => [String] })
31 public jobs?: string[];
32}
33
34const UserModel = getModelForClass(User); // UserModel is a regular Mongoose Model with correct types
35
36(async () => {
37 await mongoose.connect('mongodb://localhost:27017/', { useNewUrlParser: true, useUnifiedTopology: true, dbName: 'test' });
38
39 const { _id: id } = await UserModel.create({ name: 'JohnDoe', jobs: ['Cleaner'] } as User); // an "as" assertion, to have types for all properties
40 const user = await UserModel.findById(id).exec();
41
42 console.log(user); // prints { _id: 59218f686409d670a97e53e0, name: 'JohnDoe', __v: 0 }
43})();
44```
45
46## Motivation
47
48A common problem when using Mongoose with TypeScript is that you have to define both the Mongoose model and the TypeScript interface. If the model changes, you also have to keep the TypeScript interface file in sync or the TypeScript interface would not represent the real data structure of the model.
49
50Typegoose aims to solve this problem by defining only a TypeScript interface (class), which needs to be enhanced with special Typegoose decorators (like `@prop`).
51
52Under the hood it uses the Reflect & [reflect-metadata](https://github.com/rbuckton/reflect-metadata) API to retrieve the types of the properties, so redundancy can be significantly reduced.
53
54Instead of writing this:
55
56```ts
57// This is a representation of how typegoose's compile output would look like
58interface Car {
59 model?: string;
60}
61
62interface Job {
63 title?: string;
64 position?: string;
65}
66
67interface User {
68 name?: string;
69 age!: number;
70 preferences?: string[];
71 mainJob?: Job;
72 jobs?: Job[];
73 mainCar?: Car | string;
74 cars?: (Car | string)[];
75}
76
77const JobSchema = new mongoose.Schema({
78 title: String;
79 position: String;
80});
81
82const CarModel = mongoose.model('Car', {
83 model: string,
84});
85
86const UserModel = mongoose.model('User', {
87 name: { type: String },
88 age: { type: Number, required: true },
89 preferences: [{ type: String }],
90 mainJob: { type: JobSchema },
91 jobs: [{ type: JobSchema }],
92 mainCar: { type: Schema.Types.ObjectId, ref: 'Car' },
93 cars: [{ type: Schema.Types.ObjectId, ref: 'Car' }],
94});
95```
96
97You can just write this:
98
99```ts
100class Job {
101 @prop()
102 public title?: string;
103
104 @prop()
105 public position?: string;
106}
107
108class Car {
109 @prop()
110 public model?: string;
111}
112
113class User {
114 @prop()
115 public name?: string;
116
117 @prop({ required: true })
118 public age!: number; // This is a single Primitive
119
120 @prop({ type: () => [String] })
121 public preferences?: string[]; // This is a Primitive Array
122
123 @prop()
124 public mainJob?: Job; // This is a single SubDocument
125
126 @prop({ type: () => Job })
127 public jobs?: Job[]; // This is a SubDocument Array
128
129 @prop({ ref: () => Car })
130 public mainCar?: Ref<Car>; // This is a single Reference
131
132 @prop({ ref: () => Car })
133 public cars?: Ref<Car>[]; // This is a Reference Array
134}
135```
136
137[Extra Examples](https://typegoose.github.io/typegoose/docs/guides/quick-start-guide#extra-examples)
138
139---
140
141## Requirements & Install
142
143[Typegoose's Quick Start Guide](https://typegoose.github.io/typegoose/docs/guides/quick-start-guide)
144
145## Testing
146
147```sh
148yarn install
149yarn run test
150```
151
152## Versioning
153
154This Project should comply with [Semver](https://semver.org). It uses the `Major.Minor.Fix` standard (or in NPM terms, `Major.Minor.Patch`).
155
156## Join Our Discord Server
157
158To ask questions or just talk with us, [join our Discord Server](https://discord.gg/BpGjTTD).
159
160## Documentation
161
162* [Typegoose Documentation](https://typegoose.github.io/typegoose/docs/api/index-api)
163* [Quick start guide](https://typegoose.github.io/typegoose/docs/guides/quick-start-guide/)
164
165## Known Issues
166
167[Here are the known-issues](https://typegoose.github.io/typegoose/docs/guides/known-issues/)
168
169## FAQ
170
171[Here is the FAQ](https://typegoose.github.io/typegoose/docs/guides/faq/)
172
173## Notes
174
175* Please don't add `+1` or similar comments to issues. Use the reactions instead.