Skip to content

Commit b8e2e41

Browse files
author
Andrew Schmadel
committed
type inference for Model static methods
adds type inference to most static Model methods (create(), findAll(), etc) that previously required user-supplied generic parameters to correctly produce the correct return type.
1 parent 57f044c commit b8e2e41

File tree

11 files changed

+1933
-586
lines changed

11 files changed

+1933
-586
lines changed

lib/annotations/Column.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function annotate(target: any,
4040
};
4141
} else {
4242

43-
options = Object.assign({}, optionsOrDataType);
43+
options = Object.assign({}, <IPartialDefineAttributeColumnOptions>optionsOrDataType);
4444

4545
if (!options.type) {
4646
options.type = getSequelizeTypeByDesignType(target, propertyName);

lib/models/Model.d.ts

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export declare abstract class Model<T> extends Hooks {
5757
* @param schema The name of the schema
5858
* @param options
5959
*/
60-
static schema<T extends Model<T>>(schema: string, options?: SchemaOptions): Model<T>;
60+
static schema<T extends Model<T>>(this: (new () => T), schema: string, options?: SchemaOptions): Model<T>;
6161

6262
/**
6363
* Get the tablename of the model, taking schema into account. The method will return The name as a string
@@ -130,7 +130,7 @@ export declare abstract class Model<T> extends Hooks {
130130
* @return Model A reference to the model, with the scope(s) applied. Calling scope again on the returned
131131
* model will clear the previous scope.
132132
*/
133-
static scope(options?: string | string[] | ScopeOptions | WhereOptions<any>): typeof Model;
133+
static scope<T extends Model<T>>(this: (new () => T), options?: string | string[] | ScopeOptions | WhereOptions<any>): typeof T;
134134

135135
/**
136136
* Search for multiple instances.
@@ -194,25 +194,25 @@ export declare abstract class Model<T> extends Hooks {
194194
*
195195
* @see {Sequelize#query}
196196
*/
197-
static findAll<T extends Model<T>>(options?: IFindOptions<T>): Promise<T[]>;
197+
static findAll<T extends Model<T>>(this: (new () => T), options?: IFindOptions<T>): Promise<T[]>;
198198

199-
static all<T extends Model<T>>(options?: IFindOptions<T>): Promise<T[]>;
199+
static all<T extends Model<T>>(this: (new () => T), options?: IFindOptions<T>): Promise<T[]>;
200200

201201
/**
202202
* Search for a single instance by its primary key. This applies LIMIT 1, so the listener will
203203
* always be called with a single instance.
204204
*/
205-
static findById<T extends Model<T>>(identifier?: number | string, options?: IFindOptions<T>): Promise<T | null>;
205+
static findById<T extends Model<T>>(this: (new () => T), identifier?: number | string, options?: IFindOptions<T>): Promise<T | null>;
206206

207-
static findByPrimary<T extends Model<T>>(identifier?: number | string, options?: IFindOptions<T>): Promise<T | null>;
207+
static findByPrimary<T extends Model<T>>(this: (new () => T), identifier?: number | string, options?: IFindOptions<T>): Promise<T | null>;
208208

209209
/**
210210
* Search for a single instance. This applies LIMIT 1, so the listener will always be called with a single
211211
* instance.
212212
*/
213-
static findOne<T extends Model<T>>(options?: IFindOptions<T>): Promise<T | null>;
213+
static findOne<T extends Model<T>>(this: (new () => T), options?: IFindOptions<T>): Promise<T | null>;
214214

215-
static find<T extends Model<T>>(options?: IFindOptions<T>): Promise<T | null>;
215+
static find<T extends Model<T>>(this: (new () => T), options?: IFindOptions<T>): Promise<T | null>;
216216

217217
/**
218218
* Run an aggregation method on the specified field
@@ -267,9 +267,9 @@ export declare abstract class Model<T> extends Hooks {
267267
* without
268268
* profiles will be counted
269269
*/
270-
static findAndCount<T extends Model<T>>(options?: IFindOptions<T>): Promise<{rows: T[], count: number}>;
270+
static findAndCount<T extends Model<T>>(this: (new () => T), options?: IFindOptions<T>): Promise<{rows: T[], count: number}>;
271271

272-
static findAndCountAll<T extends Model<T>>(options?: IFindOptions<T>): Promise<{rows: T[], count: number}>;
272+
static findAndCountAll<T extends Model<T>>(this: (new () => T), options?: IFindOptions<T>): Promise<{rows: T[], count: number}>;
273273

274274
/**
275275
* Find the maximum value of field
@@ -289,30 +289,35 @@ export declare abstract class Model<T> extends Hooks {
289289
/**
290290
* Builds a new model instance. Values is an object of key value pairs, must be defined but can be empty.
291291
*/
292-
static build<T extends Model<T>>(record?: any, options?: IBuildOptions): T;
293-
static build<T extends Model<T>, A>(record?: A, options?: IBuildOptions): T;
292+
static build<T extends Model<T>>(this: (new () => T), record?: any, options?: IBuildOptions): T;
293+
static build<T extends Model<T>, A>(this: (new () => T), record?: A, options?: IBuildOptions): T;
294+
static build<A>(this: (new () => T), record?: A, options?: IBuildOptions): T;
294295

295296
/**
296297
* Undocumented bulkBuild
297298
*/
298-
static bulkBuild<T extends Model<T>>(records: any[], options?: IBuildOptions): T[];
299-
static bulkBuild<T extends Model<T>, A>(records: A[], options?: IBuildOptions): T[];
299+
static bulkBuild<T extends Model<T>>(this: (new () => T), records: any[], options?: IBuildOptions): T[];
300+
static bulkBuild<T extends Model<T>, A>(this: (new () => T), records: A[], options?: IBuildOptions): T[];
301+
static bulkBuild<A>(this: (new () => T), records: A[], options?: IBuildOptions): T[];
300302

301303
/**
302304
* Builds a new model instance and calls save on it.
303305
*/
304-
static create<T extends Model<T>>(values?: any, options?: ICreateOptions): Promise<T>;
305-
static create<T extends Model<T>, A>(values?: A, options?: ICreateOptions): Promise<T>;
306+
static create<T extends Model<T>>(this: (new () => T), values?: T, options?: ICreateOptions): Promise<T>;
307+
static create<T extends Model<T>, A>(this: (new () => T), values?: A, options?: ICreateOptions): Promise<T>;
308+
static create<A>(this: (new () => T), values?: A, options?: ICreateOptions): Promise<T>;
306309

307310
/**
308311
* Find a row that matches the query, or build (but don't save) the row if none is found.
309312
* The successfull result of the promise will be (instance, initialized) - Make sure to use .spread()
310313
*/
311-
static findOrInitialize<T extends Model<T>>(options: IFindOrInitializeOptions<any>): Promise<[T, boolean]>;
312-
static findOrInitialize<T extends Model<T>, A>(options: IFindOrInitializeOptions<A>): Promise<[T, boolean]>;
314+
static findOrInitialize<T extends Model<T>>(this: (new () => T), options: IFindOrInitializeOptions<any>): Promise<[T, boolean]>;
315+
static findOrInitialize<T extends Model<T>, A>(this: (new () => T), options: IFindOrInitializeOptions<A>): Promise<[T, boolean]>;
316+
static findOrInitialize<A>(this: (new () => T), options: IFindOrInitializeOptions<A>): Promise<[T, boolean]>;
313317

314-
static findOrBuild<T extends Model<T>>(options: IFindOrInitializeOptions<any>): Promise<[T, boolean]>;
315-
static findOrBuild<T extends Model<T>, A>(options: IFindOrInitializeOptions<A>): Promise<[T, boolean]>;
318+
static findOrBuild<T extends Model<T>>(this: (new () => T), options: IFindOrInitializeOptions<any>): Promise<[T, boolean]>;
319+
static findOrBuild<T extends Model<T>, A>(this: (new () => T), options: IFindOrInitializeOptions<A>): Promise<[T, boolean]>;
320+
static findOrBuild<A>(this: (new () => T), options: IFindOrInitializeOptions<A>): Promise<[T, boolean]>;
316321

317322
/**
318323
* Find a row that matches the query, or build and save the row if none is found
@@ -325,15 +330,17 @@ export declare abstract class Model<T> extends Hooks {
325330
* an instance of sequelize.TimeoutError will be thrown instead. If a transaction is created, a savepoint
326331
* will be created instead, and any unique constraint violation will be handled internally.
327332
*/
328-
static findOrCreate<T extends Model<T>>(options: IFindOrInitializeOptions<any>): Promise<[T, boolean]>;
329-
static findOrCreate<T extends Model<T>, A>(options: IFindOrInitializeOptions<A>): Promise<[T, boolean]>;
333+
static findOrCreate<T extends Model<T>>(this: (new () => T), options: IFindOrInitializeOptions<any>): Promise<[T, boolean]>;
334+
static findOrCreate<T extends Model<T>, A>(this: (new () => T), options: IFindOrInitializeOptions<A>): Promise<[T, boolean]>;
335+
static findOrCreate<A>(this: (new () => T), options: IFindOrInitializeOptions<A>): Promise<[T, boolean]>;
330336

331337
/**
332338
* A more performant findOrCreate that will not work under a transaction (at least not in postgres)
333339
* Will execute a find call, if empty then attempt to create, if unique constraint then attempt to find again
334340
*/
335-
static findCreateFind<T extends Model<T>>(options: IFindCreateFindOptions<any>): Promise<[T, boolean]>;
336-
static findCreateFind<T extends Model<T>, A>(options: IFindCreateFindOptions<A>): Promise<[T, boolean]>;
341+
static findCreateFind<T extends Model<T>>(this: (new () => T), options: IFindCreateFindOptions<any>): Promise<[T, boolean]>;
342+
static findCreateFind<T extends Model<T>, A>(this: (new () => T), options: IFindCreateFindOptions<A>): Promise<[T, boolean]>;
343+
static findCreateFind<A>(this: (new () => T), options: IFindCreateFindOptions<A>): Promise<[T, boolean]>;
337344

338345
/**
339346
* Insert or update a single row. An update will be executed if a row which matches the supplied values on
@@ -369,8 +376,9 @@ export declare abstract class Model<T> extends Hooks {
369376
*
370377
* @param records List of objects (key/value pairs) to create instances from
371378
*/
372-
static bulkCreate<T extends Model<T>>(records: any[], options?: BulkCreateOptions): Promise<T[]>;
373-
static bulkCreate<T extends Model<T>, A>(records: A[], options?: BulkCreateOptions): Promise<T[]>;
379+
static bulkCreate<T extends Model<T>>(this: (new () => T), records: any[], options?: BulkCreateOptions): Promise<T[]>;
380+
static bulkCreate<T extends Model<T>, A>(this: (new () => T), records: A[], options?: BulkCreateOptions): Promise<T[]>;
381+
static bulkCreate<A>(this: (new () => T), records: A[], options?: BulkCreateOptions): Promise<T[]>;
374382

375383
/**
376384
* Truncate all instances of the model. This is a convenient method for Model.destroy({ truncate: true }).
@@ -394,8 +402,9 @@ export declare abstract class Model<T> extends Hooks {
394402
* elements. The first element is always the number of affected rows, while the second element is the actual
395403
* affected rows (only supported in postgres with `options.returning` true.)
396404
*/
397-
static update<T extends Model<T>>(values: any, options: UpdateOptions): Promise<[number, Array<T>]>;
398-
static update<T extends Model<T>, A>(values: A, options: UpdateOptions): Promise<[number, Array<T>]>;
405+
static update<T extends Model<T>>(this: (new () => T), values: any, options: UpdateOptions): Promise<[number, Array<T>]>;
406+
static update<T extends Model<T>, A>(this: (new () => T), values: A, options: UpdateOptions): Promise<[number, Array<T>]>;
407+
static update<A>(this: (new () => T), values: A, options: UpdateOptions): Promise<[number, Array<T>]>;
399408

400409
/**
401410
* Run a describe query on the table. The result will be return to the listener as a hash of attributes and
@@ -406,7 +415,7 @@ export declare abstract class Model<T> extends Hooks {
406415
/**
407416
* Unscope the model
408417
*/
409-
static unscoped(): typeof Model;
418+
static unscoped<T extends Model<T>>(this: (new () => T)): typeof T;
410419

411420
/**
412421
* A reference to the sequelize instance

0 commit comments

Comments
 (0)