2

I'm trying to relate two models with an extra property of "url":

if (typeof session.id === "number") {
  const sessionUser = await Session.relatedQuery("users")
    .for(session.id)
    .relate({
      id: 12345, // error here
      url: "test",
    });
}

The error I get from typescript is this:

Argument of type '{ id: number; url: string; }' is not assignable to parameter of type 'string | number | CompositeId | MaybeCompositeId[] | PartialModelObject | PartialModelObject[]'. Object literal may only specify known properties, and 'id' does not exist in type 'CompositeId | MaybeCompositeId[] | PartialModelObject | PartialModelObject[]'.

However, if I try to relate the models without the extra property, it works perfectly:

if (typeof session.id === "number") {
  const sessionUser = await Session.relatedQuery("users")
    .for(session.id)
    .relate(userId); //userId is just a number e.g. 5
}

Here's my Session model. I also have the extra property on my User model too, as a safety net:

export class Session extends Model {
  host_id?: number;
  url?: string;

  static get tableName() {
    return "sessions";
  }

  static relationMappings = {
    users: {
      relation: Model.ManyToManyRelation,
      modelClass: path.join(__dirname, "User"),
      join: {
        from: "sessions.id",
        through: {
          from: "sessions_users.session_id",
          to: "sessions_users.user_id",
          extra: ["url"],
        },
        to: "users.id",
      },
    },
  };
}

Here are the docs for extra properties: https://vincit.github.io/objection.js/recipes/extra-properties.html

Am I missing anything obvious here?

Andy
  • 364
  • 1
  • 8
  • 21
  • 1
    Please replace the images in this question with the corresponding text, as requested in [ask], for all the reasons mentioned [here](https://meta.stackoverflow.com/questions/285551/why-not-upload-images-of-code-errors-when-asking-a-question/285557#285557). – jcalz Jan 28 '21 at 14:39
  • 1
    Whoops, images have been replaced – Andy Jan 28 '21 at 14:44
  • 2
    I don't know anything about objection.js, so it's possible someone else will come along who knows enough about it to answer with the info as given. If you'd like the question to be easier for others to answer, please consider providing a [mcve] suitable for dropping into a standalone IDE like [The TypeScript Playground](https://tsplay.dev/KwXYDN) and/or furnishing a link to a properly-configured project in a web IDE, which demonstrates your problem. If you can lower the bar for others to reproduce your issue, you will increase the chances of getting a helpful answer. Good luck! – jcalz Jan 28 '21 at 14:50
  • 1
    I don't know `objection.js` either but the type of [relate](https://github.com/Vincit/objection.js/blob/f78fbf5a09c9b3e548b0bb21926db6c48e322c8f/typings/objection/index.d.ts#L1010) and the documentation about [relate](https://vincit.github.io/objection.js/api/query-builder/mutate-methods.html#relate) makes me think that you are using it wrong. It seems that you cannot pass an object as parameter of relate. – Orelsanpls Jan 28 '21 at 14:53
  • I thought so too, but you can see in the official docs an object is passed to relate: https://vincit.github.io/objection.js/recipes/extra-properties.html. It's in the bottom example, where it says "Relate an existing movie with a `characterName`." – Andy Jan 28 '21 at 15:19

1 Answers1

4

I don't think type inference is capable of understanding which model you're referring to here. I suspect the simple approach is going to look like:

.relate({
  id: 12345,
  url: "test",
} as PartialModelObject<User>);

This as an alternative to declaring the object literal ahead of time, like:

const related: PartialModelObject<User> = { id: 12345, url: "test" };

Untested, but that's the general idea.

Rich Churcher
  • 7,361
  • 3
  • 37
  • 60