lucid icon indicating copy to clipboard operation
lucid copied to clipboard

A weird TypeScript error when lazy loading a related entity

Open irshadahmad21 opened this issue 1 year ago • 10 comments

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.

Screenshot 2024-12-23 at 9 57 58 PM
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

irshadahmad21 avatar Dec 23 '24 16:12 irshadahmad21

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?

RomainLanz avatar Dec 23 '24 16:12 RomainLanz

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

thetutlage avatar Dec 24 '24 04:12 thetutlage

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

irshadahmad21 avatar Dec 24 '24 09:12 irshadahmad21

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.

irshadahmad21 avatar Dec 26 '24 11:12 irshadahmad21

Hello guys! Any update on this issue?

luiscosilva avatar Feb 28 '25 13:02 luiscosilva

running into the same issue

jonhester avatar Mar 28 '25 15:03 jonhester

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.

jonhester avatar Mar 28 '25 16:03 jonhester

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.

atassis avatar Jun 02 '25 11:06 atassis

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.

manomintis avatar Jul 30 '25 17:07 manomintis