A weird TypeScript error when lazy loading a related entity
Package version
21.5.1
Describe the bug
I have relations with the simplified version being this
import { BaseModel, belongsTo, column } from '@adonisjs/lucid/orm';
import type { BelongsTo } from '@adonisjs/lucid/types/relations';
class Client extends BaseModel {
@column({ isPrimary: true })
declare id: number;
}
class Project extends BaseModel {
@column({ isPrimary: true })
declare id: number;
@column()
declare name: string;
@column()
declare clientId: string;
@belongsTo(() => Client)
declare client: BelongsTo<typeof Client>;
}
class Task extends BaseModel {
@column({ isPrimary: true })
declare id: number;
@column()
declare projectId: string;
@belongsTo(() => Project)
declare project: BelongsTo<typeof Project>;
async getProjectName(this: Task) {
await this.load('project');
return this.project.name;
}
}
I see an error on that this.load('project') call.
No overload matches this call.
Overload 1 of 2, '(callback: (preloader: PreloaderContract<Task>) => void): Promise<void>', gave the following error.
Argument of type 'string' is not assignable to parameter of type '(preloader: PreloaderContract<Task>) => void'.
Overload 2 of 2, '(relation: undefined, callback?: ((builder: never) => void) | undefined): Promise<void>', gave the following error.
Argument of type '"project"' is not assignable to parameter of type 'undefined'.
It used to work fine in version 20.4.0. May be something changed in version 21.
Reproduction repo
No response
Hey there! 👋🏻
This reminds me of an older TypeScript bug: microsoft/TypeScript#37778.
I'm not certain they're related, but does the issue persist if you downgrade Lucid or TypeScript? Also, could you create a minimal repository demonstrating the problem?
This reminds me of an older TypeScript bug: https://github.com/microsoft/TypeScript/issues/37778.
Its the same issue, since it was never fixed in the first place by the TypeScript team
It may not be related to that bug because it works fine in Lucid v20 but breaks in v21.
Here are the minimal reproducible setups
With v20 (Build succeeds) https://stackblitz.com/edit/vitejs-vite-8houbyjt?file=package.json
With v21 (Build fails) https://stackblitz.com/edit/vitejs-vite-xcvgsb1y?file=package.json
I think the bug was introduced in https://github.com/adonisjs/lucid/commit/532b9cb85a290b5dc0a7c7cdd29ee4707cd71a35.
If you change
extends ModelRelations<LucidModel, LucidModel>
to
extends ModelRelations<infer _, infer __>
in
type ExtractModelRelations<Model extends LucidRow> = {
[Key in keyof Model]: Model[Key] extends ModelRelations<LucidModel, LucidModel> ? Key : never;
}[keyof Model];
That may fix the issue. I don't know if that can have any other implications.
Hello guys! Any update on this issue?
running into the same issue
Nevermind on my issue, turns out it was because I was naming my relationships client and its used internally. Seems like that should at least be namespaced or something because that seems like a pretty common word to use and the type error is not helpful at all there.
What is a status of this? I have exactly the same issue.
On @adonisjs/[email protected] everything is fine. So degradation of type safety is introduced in @adonisjs/[email protected]
UPD: I have not exactly the same issue, but it might still be related. I have 2 models related to each other via one to many relation. I have an error when I try to associate a belonged model await belonged.related('parent').associate(parent);. I see that description is not that readable, I'll later create a repo to show an error.
I've just faced the same issue. It only happens in User model for me because it differs from a default stub. More details below.
User model stub class extends compose() but not just BaseModel, which is probably required for implementing authentication. However, this causes a Typescript error if loading relationships.
I added a relationship:
@hasMany(() => Code)
declare codes: HasMany<typeof Code>
Then I tried to load it:
await this.load('codes')
'codes' becomes underlined with red and the error is:
Argument of type 'string' is not assignable to parameter of type 'ExtractModelRelations<this>'.ts(2345)
Therefore, I have to rewrite the code like that:
await this.load('codes' as any)
It works but I guess it is not supposed to be like that.