-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove FlattenMaps due to issues with private and protected fields #13523
Comments
What does your Quote type look like - do you use maps? This change was intentional because |
Hi @vkarpov15 , As always, really appreciate your prompt replies. What do you mean by maps in this context? Our Quote is a complex object a gist of the Typescript interface definition is below -
We have a schema typed to the above interface and we having been using calls to .lean() or aggregations to get our data as POJO in that shape. |
JavaScript's Also, does TypeScript give you any more hints about why exactly |
Hi @vkarpov15, We do not use Javascript Maps in interfaces. It seems that the issue may be related to a specific type call Lex. This is a LexoRank object (Jira style ordering) or string. The Mongoose schema is set to String. The LexoRank object will serialize to string and were not having any issues using it with Mongoose before. Here is a full typescript error for Quote.
Here is another model called OpportunityView -
I hope this helps |
What does the LexoRank type look like? |
LexoRank is a class with methods and has on two class level fields. Below is a gist of the class and I have removed the body of most methods. We are expecting the toString value to persist to the database.
|
I suspect the issue is the private fields. It doesn't look like TypeScript can iterate over private fields when creating a copy of a class. For example, the following script fails to compile with a import { FlattenMaps } from 'mongoose';
export class LexoRank {
constructor(
readonly value: string,
readonly bucket = '0'
) {
this.value = value;
this.bucket = bucket;
}
public toString() {
return `${this.bucket}|${this.value}`;
}
private append(str: string) {}
}
type T1 = (FlattenMaps<LexoRank>) | string;
const X: T1 = new LexoRank('foo', '0');
const X2: LexoRank = X; We're investigating this and looking for a workaround. |
Realistically, there's no good way for Mongoose to support classes with private members with We should consider removing @hasezoey @AbdelrahmanHafez what do you think? Keep FlattenMaps or remove? |
from my understanding also from what i can tell, typescript is correct, you cannot assign a object that looks like so there is either we let
some example code // NodeJS: 20.2.0
// MongoDB: 5.0 (Docker)
// Typescript 4.9.5
import * as mongoose from 'mongoose'; // mongoose@7.3.1
class SomeClass {
public test!: string;
public method() {}
// private testprop!: string;
// private pmethod() {}
}
interface Test {
class: SomeClass;
}
interface TestPOJO {
class: Pick<SomeClass, keyof SomeClass>;
}
// function is expected to return a "Test" interface with a instance of "SomeClass" at "class"
function test(): Test /* TestPOJO */ {
// using undefined just as a placeholder for types
const t = undefined as any as mongoose.FlattenMaps<Test>;
t.class.method(); // type does not error, but is incorrect and does not work at runtime in .lean
return t; // return works without protected or private fields or methods
} uncommenting either |
Prerequisites
Mongoose version
7.3.0
Node.js version
16
MongoDB server version
v18.16.0
Typescript version (if applicable)
5.1.3
Description
We have recently upgrade Mongoose from v7.0.3 -> v7.3.0 and noticed that calls to lean are now returning the Model type wrapped with FlattenMaps.
For example we we previously had a model typed in the following way -
Since v7.3.0 we have over 100 typescript errors complaining -
To enable us to build we to do the following -
Steps to Reproduce
Please see description above
Expected Behavior
The expected behaviour is that calls to to lean with be type to the T used by model unless overridden like I have done in my example above.
The text was updated successfully, but these errors were encountered: