Reputation: 21
I am trying to set up a base repository
class between Mikro-orm and my services, in order to have a simple interface and swap the implementation for another framework if the technology stack requires it.
However, the FilterQuery
doesn't seem to accept {_id: ObjectId}
as an argument:
abstract class MyBaseEntity {
@PrimaryKey()
_id: ObjectId;
@SerializedPrimaryKey()
id!: string; // won't be saved in the database
[PrimaryKeyType]: [ObjectId, string]; // i've set this up in the hope it would pick it up in the type check
}
class BaseRepositoryImpl<Entity extends MyBaseEntity> {
private collection: EntityRepository<Entity>;
constructor(
private repository: EntityRepository<Entity>
) {
this.collection = repository;
}
async findOne(id: ObjectId): Promise<Entity | null> {
const result = this.collection.findOne({_id: id}); //'{ _id: ObjectId; }' is not assignable to parameter of type 'FilterQuery<Entity>
// and '_id' does not exist in type '{ [PrimaryKeyType]?: any; }
return result;
}
}
Upvotes: 0
Views: 488
Reputation: 18389
There is no need to specify the PK type, objectid/string duality is handled automatically. Also, [PrimaryKeyType]: [ObjectId, string]
means "ordered tuple of object id and string, aka composite PK - but those are not supported in mongo at all. You might want to try [PrimaryKeyType]: ObjectId | string
instead, but again, should not be needed.
The issue here is TS, using extends
in generic type parameter is not enough. Check this snippet to see the fundamental problem:
interface Base {
id: string;
}
interface Entity extends Base {
name: string;
}
function fun<T extends Entity>(e: T) {
e = { id: '1', name: 'n' }; // Type '{ id: string; name: string; }' is not assignable to type 'T'.
}
In other words, this is a TS limitation and you will need to type cast.
Upvotes: 1