Nesting Classes
Differences from Mongoose
Typegoose Nesting is slightly different from mongoose, the following will show a basic mongoose schema which has nesting and how it would be translated to typegoose.
- Mongoose
- Typegoose
const AnimalSchema = new mongoose.Schema({
name: String,
properties: {
hasEaten: Boolean,
nicknames: [String]
}
});
class Animal {
@prop()
public name?: string;
@prop()
public properties?: Properties;
}
class Properties {
@prop()
public hasEaten?: boolean;
@prop({ type: String })
public nicknames?: string[];
}
It is required to put nested properties in their own class because of how typescript reflection works, it currently just translates { someprop: string }
to Object
in reflection.
Also, under the hood, typegoose creates the schemas that would be equivalent to writing:
const PropertiesSchema = new mongoose.Schema({
hasEaten: {
type: Boolean
},
nicknames: [{
type: String
}]
});
const AnimalSchema = new mongoose.Schema({
name: {
type: String
},
properties: {
type: PropertiesSchema
}
});
Typegoose does not support native "nested paths" (unless using Passthrough
), each class in typegoose will be a nested schema (each class is its own Schema
instance), so it is not a 1:1 translation of the initial mongoose example to typegoose, but similar enough to initially think that way.
Using the Passthrough Class
It is not recommended to use the Passthrough
Class unless explicitly required to workaround something. In case you have found a problem that could only be solved with the Passthrough class, please open a new issue in the typegoose repository so that we can fix having to use the Passthrough Class.
In Typegoose there also exists a special class called Passthrough
which can be used to write a mongoose schema-like directly, without typegoose processing it.
Here is a Example of how a mongoose schema would look like writing it with Passthrough
:
- Mongoose
- Typegoose
Mongoose Initial Schema:
const AnimalSchema = new mongoose.Schema({
name: String,
properties: {
hasEaten: Boolean,
nicknames: [String]
}
});
And the Typegoose Equivalent with Passthrough
(using the Direct
mode):
class Animal {
@prop()
public name?: string;
@prop({ type: () => new Passthrough({ hasEaten: Boolean, nicknames: [String] }, true) })
public properties?: { hasEaten: boolean, nicknames: string[] };
}
With Passthrough
and the Direct
mode, the typegoose class above is fully equivalent in how it is given to mongoose as the mongoose schema example.
Difference to References
In Typegoose, references and subdocuments are written similarly:
- Subdocument
- Reference
- Difference
class Animal {
@prop()
public name?: string;
@prop()
public properties?: Properties;
}
class Properties {
@prop()
public hasEaten?: boolean;
@prop({ type: String })
public nicknames?: string[];
}
class Animal {
@prop()
public name?: string;
@prop({ ref: () => Properties })
public properties?: Ref<Properties>;
}
class Properties {
@prop()
public hasEaten?: boolean;
@prop({ type: String })
public nicknames?: string[];
}
class Animal {
@prop()
public name?: string;
- @prop()
- public properties?: Properties;
+ @prop({ ref: () => Properties })
+ public properties?: Ref<Properties>;
}
class Properties {
@prop()
public hasEaten?: boolean;
@prop({ type: String })
public nicknames?: string[];
For more on referencing other classes, read Reference other Classes.