Description
Issue Description
Currently when running a query with a model in Typescript, the result(s) are instances of the model.
e.g.
import { Model } from 'sequelize';
class Foo extends Model {};
async () => {
// Foo.findAll() returns Promise<Foo[]>
const foos: Foo[] = await Foo.findAll();
};
This is expected and ideal behavior.
However when running a query with raw: true
(https://sequelize.org/master/manual/raw-queries.html) the response is very much not an instance of the model (what it is is up for discussion in this issue).
The typing for queries that support raw should support returning non-model responses.
async () => {
const foos: = await Foo.findAll({
attributes: [[fn('RAND'), 'random']],
raw: true,
});
foos.forEach(foo => {
// Typescript fails on `random` is not on `Foo`
console.log(foo.random);
});
};
What was unclear/insufficient/not covered in the documentation
Presently, all Model query methods that support {raw: true}
still declare they return the model instance, when raw queries are explicitly not instances.
So regular model attributes like get
are not even available (which are used as a workaround for custom attributes on non-raw results).
If possible: Provide some suggestion on how we can enhance the docs
Allow type parameters on methods that support raw: true
to return a custom type, defaulting to the models raw attributes.
As an example, below is the existing definition for findAll: https://github.com/sequelize/sequelize/blob/v6/types/lib/model.d.ts#L1826
public static findAll<M extends Model>(
this: ModelStatic<M>,
options?: FindOptions<M['_attributes']>): Promise<M[]>;
If we added another method definition that explicitly declared when raw: true
to return a type parameter, it could correctly handle typing raw queries:
public static findAll<M extends Model>(
this: ModelStatic<M>,
options?: FindOptions<M['_attributes']> & { raw?: false }): Promise<M[]>;
public static findAll<M extends Model, R extends any = M['_attributes']>(
this: ModelStatic<M>,
options?: FindOptions<M['_attributes']> & { raw: true }): Promise<R[]>;
The example query above could now be supported as:
Foo.findAll<Foo, { random: number }>({
attributes: [fn('RAND'), 'random'],
raw: true,
})
Additional context
If there is another known method (or suggestions) for typing raw queries I'd appreciate the advice.
I know it is possible to just run the query as raw: false
and use getters to load the custom attributes, but I believe raw queries serve their purpose when the extra noise of model instances is unnecessary. Not to mention the current typing is objectively wrong in this case.
Issue Template Checklist
Is this issue dialect-specific?
- No. This issue is relevant to Sequelize as a whole.
- Yes. This issue only applies to the following dialect(s): XXX, YYY, ZZZ
- I don't know.
Would you be willing to resolve this issue by submitting a Pull Request?
Happy to make an actual PR with my suggested findAll()
as well as a couple others (possibly findOne
+ findByPk
?) if the solution sounds correct
- Yes, I have the time and I know how to start.
- Yes, I have the time but I don't know how to start, I would need guidance.
- No, I don't have the time, although I believe I could do it if I had the time...
- No, I don't have the time and I wouldn't even know how to start.