Skip to content
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

Can't seem to type my functions correctly (using discriminator models) #14273

Closed
1 task done
jpl-ivengi opened this issue Jan 19, 2024 · 3 comments
Closed
1 task done
Labels
help wanted help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary typescript Types or Types-test related issue / Pull Request

Comments

@jpl-ivengi
Copy link

Prerequisites

  • I have written a descriptive issue title

Mongoose version

6.12.5

Node.js version

18.19.0

MongoDB version

5.0

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

Sonoma 14.2.1

Issue

There are a number of situations where I seem to fail in writing the correct typing to make the typescript code work.

I've defined my models as follow

interface IBase {
  nameBase: string;
}

interface IDiscriminator extends IBase {
  nameDiscriminator: string;
}

const baseSchema = new mongoose.Schema<IBase>();
const discriminatorSchema = new mongoose.Schema<IDiscriminator>();

const BaseModel = mongoose.model<IBase>('base', baseSchema);
const DiscriminatedModel = BaseModel.discriminator<IDiscriminator>('discriminator', discriminatorSchema);

The following works without issues:

class TestClass {
  public testFunction<T extends IBase>(M: mongoose.Model<T>) {
    console.log(M);
  }
}

const testClass = new TestClass();
testClass.testFunction(BaseModel);
testClass.testFunction(DiscriminatedModel);

When moving the generic typing to the class definition it doesn't work, the code:

class TestClass2<X extends IBase> {
  public testFunction(M: mongoose.Model<X>) {
    console.log(M);
  }
}

const testClass2 = new TestClass2();
testClass2.testFunction(BaseModel);
testClass2.testFunction(DiscriminatedModel);

Displays an error on the last function call's argument (testClass2.testFunction(DiscriminatedModel);

TS2345 - Argument of type Model<IDiscriminator..... is not assignable to type Model<IBase......

But I don't seem to understand why moving the generic triggers the error since (to me) it looks like it hasn't changed the inference between the 2 ways of writing the code.

@jpl-ivengi jpl-ivengi added help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary help wanted labels Jan 19, 2024
@vkarpov15 vkarpov15 added this to the 8.1.1 milestone Jan 21, 2024
@vkarpov15 vkarpov15 added the typescript Types or Types-test related issue / Pull Request label Jan 21, 2024
@vkarpov15 vkarpov15 modified the milestones: 8.1.1, 6.12.6, 6.12.7 Jan 21, 2024
@valeriuflorescu16
Copy link
Contributor

The main difference here is that the in the first instance, the generic type is defined at method level - each time you call testFunction, you can pass in a different type (one that is valid, so it has to extend IBase, which it does in your scenario so everything works well).

In TestClass2, the generic parameter is defined at class level, which is where the issue lies. Once you create an instance of TestClass2, the generic type is fixed for that instance. So if you were to replace const testClass2 = new TestClass2(); with const testClass2 = new TestClass2<IDiscriminator>(); then you would see the type error on the call of the function with BaseModel, and the second one would be fine.

So basically, you have more flexibility when defining the generic parameter at method level. 👍

Copy link

This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days

@github-actions github-actions bot added the Stale label Feb 14, 2024
@vkarpov15 vkarpov15 removed the Stale label Feb 14, 2024
@vkarpov15
Copy link
Collaborator

The issue is that, while X extends IBase, there's no guarantee that mongoose.Model<X> extends mongoose.Model<IBase> in the following code.

class TestClass2<X extends IBase> {
  public testFunction(M: mongoose.Model<X>) {
    console.log(M);
  }
}

I'd recommend @valeriuflorescu16 's approach: define the generic at the method level, not the class level. TypeScript doesn't have a way for us to tell the compiler that mongoose.Model<IDiscriminator> extends mongoose.Model<IBase>.

@vkarpov15 vkarpov15 removed this from the 6.12.7 milestone Feb 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary typescript Types or Types-test related issue / Pull Request
Projects
None yet
Development

No branches or pull requests

3 participants