we are currently blocked by some typescript typings on the ORM part of our project. We are running our own for some legacy/obscure reasons.
What we'd need now is to be able to correctly type the model's query where conditions to account for relations. Here's an example:
interface Model1{
id:string;
name:string;
childId:string;
}
interface Model1Relations{
child:Model2;
}
type Model1WithRelations = Model1 & Model1Relations;
interface Model2{
id:string;
name:string;
}
Pretty straightforward, Model1 uses childId for the belongsTo relation. We have intermediary interfaces that map the relations parts. This allows us to use the basic interface for inserts and updates etc, and the other Model1WithRelations on the selects.
When we add a where clause to our query, we define it with an object like so: {name:"Bob"}
. The typing is easily done using Partial. (To keep it simple, because we also allow for operators like lowerThan, not equal, includedIn etc).
Now, we have (finally) created native joins on our queries and we can now search entities according to their relations. If I want to get the model1 that has Bob as its child, I can do {"child.name":"Bob"}
, but this does not fulfill the type requirements.
If we use Partial instead, we get to make types work if we change the way we write the where like so: {child:{name:"Bob"}}
but we feal it makes things harder to read and understand, considering the conditions can get wild when paired with ANDs, ORs and a couple different operators which are defined by passing an object already like {name:{like:"%bob%"}}
Is it do-able? Can we achieve what we are looking for? Which is concatenating a property name with it's type's property names? I find it hard to believe that this is something possible... So if not, what would you suggest we do, what are others doing about this? I see most other ORMs simply do not type their conditions firmly and we feel it causes harm.
CodePudding user response:
I'm not sure I fully understood your question but here is something you can do:
type ModelRelationsConcatenated<T> = {
[K in keyof T[keyof T] as `${Exclude<keyof T, symbol>}.${Exclude<K, symbol>}`]: T[keyof T][K];
}
This is just an example to show it is possible, but you might wanna do some changes to this to better suit your use case.