Typegoose: Array Methods

Created on 12 May 2020  路  10Comments  路  Source: typegoose/typegoose

Which feature

Why do you want it

It is useful for work with sub-document arrays to have methods like .create or .id

Additional Notes

Made a test and the methods are there still available on the components, just not exported by typescript, if someone has some guidance on how that could be implemented I could give it a try!

question

Most helpful comment

@Negan1911 thanks, this was really an problem - didnt notice

All 10 comments

if you want to use these functions, you have to define the arrays with them, here an example:

// NodeJS: 12.16.2
// MongoDB: 4.2-bionic (Docker)
import { getModelForClass, prop, arrayProp, DocumentType } from "@typegoose/typegoose"; // @typegoose/[email protected]
import * as mongoose from "mongoose"; // [email protected]

class Nested {
  @prop({ required: true })
  public someprop!: string;
}

class Parent {
  @arrayProp({ items: String })
  public normalArray!: mongoose.Types.Array<string>;

  @arrayProp({ items: Nested })
  public documentArray!: mongoose.Types.DocumentArray<DocumentType<Nested>>;
}
const ParentModel = getModelForClass(Parent);

(async () => {
  await mongoose.connect(`mongodb://localhost:27017/`, { useNewUrlParser: true, dbName: "verify255", useCreateIndex: true, useUnifiedTopology: true });

  const doc = await ParentModel.create({ normalArray: ["hi", "Hello"], documentArray: [{ someprop: "Hello" }, { someprop: "hi" }] });

  console.log(doc);
  doc.documentArray.create({ someprop: "Another hello" });
  doc.normalArray.$pop();
  await doc.save();
  console.log(doc);

  await mongoose.disconnect();
})();

That worked great! quick question, do you think that would make sense to add a custom type on typegoose on charge of that, so you could use it as.

// Considering DocumentArray is a type exported from typegoose
class Parent {
  @arrayProp({ items: String })
  public normalArray!: DocumentArray<string>; // If primitive, will infer mongoose.Types.Array<string>

  @arrayProp({ items: Nested })
  public documentArray!: DocumentArray<Nested>; // If class, will infer mongoose.Types.DocumentArray<DocumentType<Nested>>
}

I think that would be a neat addition, and I could try to work on it!

sorry, but this could lead to problems, like custom types


i think the issue is solved, closing it

Sure, thanks for your time on this!

At first I thought that this was working fine, but once deployed I started seeing some issues, looks like the metadata is not recognizing mongoose.Types.DocumentArray as an array, because I get:

WARN You might not want to use option "items" for an non-array @prop type (Account.branches)
WARN Implicitly setting "Mixed" is not allowed! (Account, branches)
INFO    TypeError: this.branches.id is not a function

Where my code is

class Account {
  @prop({ default: '' })
  name: string

  @arrayProp({ items: Branch, default: [] })
  branches: mongoose.Types.DocumentArray<DocumentType<Branch>>

@Negan1911 thanks for reporting, will be fixed in next version, for now you can overwrite it @prop({}, WhatIsIt.Array)

(fixed in: d2165fecc1c10455d2fdb163d3cc3f79cce96a62)

@hasezoey Before you publish that fix, I've applied your commit using patch-package on the lib/props.js file, and got this error:

{
    "errorType": "ObjectExpectedError",
    "errorMessage": "Tried to set nested object field `branches` to array `` and strict mode is set to throw.",
    "message": "Tried to set nested object field `branches` to array `` and strict mode is set to throw.",
    "name": "ObjectExpectedError",
    "path": "branches",
    "stack": [
        "ObjectExpectedError: Tried to set nested object field `branches` to array `` and strict mode is set to throw.",
        "    at new ObjectExpectedError (/var/task/node_modules/mongoose/lib/error/objectExpected.js:24:11)",
        "    at SingleNestedPath.cast (/var/task/node_modules/mongoose/lib/schema/SingleNestedPath.js:156:11)",
        "    at SingleNestedPath.SchemaType.applySetters (/var/task/node_modules/mongoose/lib/schematype.js:1031:12)",
        "    at SingleNestedPath.SchemaType.getDefault (/var/task/node_modules/mongoose/lib/schematype.js:968:25)",
        "    at $__applyDefaults (/var/task/node_modules/mongoose/lib/document.js:405:22)",

That is because how mongoose schema types are being interpreted, I think that for subdocuments typegoose is assigning the type and not [type].
I had been trying to track where does that happens but cannot found it.

@Negan1911 currently its always surround as long as whatis is set to WhatIsIt.Array, this error seems to try to set "undefined/null" to property "branches" of some class

If I apply @prop({}, WhatIsIt.Array) I get:

console.warn
    You might not want to use option "items" for an non-array @prop type (Account.branches)

I'm guessing but WhatIsIt.ARRAY is 0 and maybe is not being caught on this line?
(Since WhatIsIt.ARRAY equals 0 also equals false).

Replacing if (!kind) with if (kind === null || kind === undefined) fixes this issue.

I'm still looking why when I apply the patch I get that error, which doesn't happen on any other case (it also doesn't happen on jest). Guessing maybe ts-loader is going nuts or something else, will let you know if I found anything useful

EDIT: Forgot to say, I really appreciate the time you are putting on this!
EDIT2: Found the reason why my patch was not working (causing the Tried to set nested object fieldbranchesto array `` error), is not because of this project!

@Negan1911 thanks, this was really an problem - didnt notice

Was this page helpful?
0 / 5 - 0 ratings

Related issues

huming2207 picture huming2207  路  8Comments

rubenvereecken picture rubenvereecken  路  5Comments

remidej picture remidej  路  7Comments

akash-rajput picture akash-rajput  路  4Comments

hasezoey picture hasezoey  路  6Comments