Open ldiego08 opened 4 years ago
// a bit of helpers
export class Command<T> implements ICommand {
private $resultType!: T
}
export class Query<T> implements IQuery {
private resultType!: T
}
// declarations.d.ts - extension to @nestjs/cqrs
declare module '@nestjs/cqrs/dist/query-bus' {
export interface QueryBus {
execute<X>(query: Query<X>): Promise<X>
}
export type IInferringQueryHandler<
QueryType extends Query<unknown>
> = QueryType extends Query<infer ResultType>
? IQueryHandler<QueryType, ResultType>
: never
}
declare module '@nestjs/cqrs/dist/command-bus' {
export interface CommandBus {
execute<X>(command: Command<X>): Promise<X>
}
export type IInferringCommandHandler<
CommandType extends Command<unknown>
> = CommandType extends Command<infer ResultType>
? {
execute(command: CommandType): Promise<ResultType>
}
: never
}
Then
class SomeQuery extends Query<Dto[]> {
constructor() {
super()
}
}
@QueryHandler(SomeQuery)
export class SomeQueryHandler
implements IInferringQueryHandler<SomeQuery> { ... }
We often use such enhancement/path to not add additional generics but just letting to infer the result type.
(code credits to @Dyostiq)
@ldiego08 and others:
we have released the package that may be useful to achieve the above:
https://github.com/valueadd-poland/nestjs-packages/tree/master/packages/typed-cqrs
@kamilmysliwiec the solution provided by @kgajowy can be easily added to the nestjs/cqrs package with backward compatibility using overloading.
MediatR (.NET) has this and it is sorely missed in my NodeJS projects.
This would be extremely handy for project I am now working on. I think this should be bumped to higher priority, it would be a very well-received feature for reducing verbosity.
@aeoncleanse you can already use this addon https://github.com/valueadd-poland/nestjs-packages/tree/master/packages/typed-cqrs
Out of curiosity, Now that nestJS 8 is here are you planning to release a new version of this or it's supported ? @Sikora00
@mohit-singh-pepper I can release it this week. Basically it's just a change to the package.json. It works the same with --force install
@mohit-singh-pepper v1.0.0 released :)
I removed dependency on any specific version of @nestjs/cqrs
In the meantime, I've been accomplishing this with the following (admittedly verbose) typing:
queryBus.execute<
FooQuery,
Awaited<ReturnType<FooQueryHandler['execute']>>
>(new FooQuery(fooId))
Awaited
type comes from TypeScript 4.5.
Is there any update here? We are really missing this functionality in our applications and would rather not depend on an external library for this. Seems like a very good option to add. I can also create the PR if needed.
So was this abandoned or can we expect an update any time soon?
@kamilmysliwiec if a PR was created for this, would you consider it? Thanks
I'm submitting a...
Current behavior
Getting a strongly-typed result from
QueryBus.execute()
involves specifying theTRes
type parameter, but since it's the second one, you also have to specify the type of the query (inferred when no type params are specified).According to this answer https://github.com/nestjs/cqrs/issues/167#issuecomment-628462104, considering the following query...
... the intended use if you want a strongly-typed result would be:
Expected behavior
If
TRes
was the first parameter, it would be less verbose:Examining a bit deeper, I started wondering why is not the result type inferred along with the query type, i.e.:
execute
could potentially infer the type if its definition was:I'm aware that
QueryBase
is already being used as the generic type for the entireQueryBus
class. Does that mean I should inject as many query buses as query types I'm intending to execute?While the implementation hints so, docs specify otherwise: the
QueryBus
is a generic class. With all the above said, I have some questions:Is there a particular reason
QueryBase
is a class-level type parameter inQueryBus
instead of a method-level one inexecute
?Would it be okay to move the
TRes
type param first?Environment