1- import { PersistenceInfo , WithId } from "./types" ;
1+ import { ModelAttributes , ModelType , PersistenceInfo , WithId , WithOptionalId } from "./types" ;
22
33/**
44 * Base class for all models. Set persistence information using the `Persistence` decorator.
55 */
6- export class Model < T , C = any > {
7- protected static persistence : PersistenceInfo < any , any > ;
6+ export class Model < T extends ModelAttributes > {
7+ protected static persistence : PersistenceInfo < Model < any > > ;
88 protected data : T = { } as T ;
99 protected changedFields : Set < string > = new Set ( ) ;
1010 protected _persisted : boolean ;
@@ -15,8 +15,8 @@ export class Model<T, C = any> {
1515 *
1616 * @returns The persistence information configured for this model.
1717 */
18- public static getPersistence < T , C > ( ) {
19- return this . persistence as PersistenceInfo < T , C > ;
18+ public static getPersistence < T extends ModelAttributes > ( ) {
19+ return this . persistence as PersistenceInfo < Model < T > > ;
2020 }
2121
2222 /**
@@ -68,7 +68,7 @@ export class Model<T, C = any> {
6868 * @param data - The data to initialize the model with.
6969 * @param persisted - Whether the model is already persisted to the database.
7070 */
71- constructor ( data : T & { id ?: any } , persisted : boolean = false ) {
71+ constructor ( data : WithOptionalId < T > , persisted : boolean = false ) {
7272 // TODO: generate ID using context
7373 this . id = data . id ;
7474 const { id, ...rest } = data ;
@@ -89,9 +89,9 @@ export class Model<T, C = any> {
8989 * @param value - The value to set the field to, if setting a single field. Ignored otherwise.
9090 * @returns The model instance.
9191 */
92- public set < K extends keyof T > ( key : K , value : T [ K ] ) : Model < T , C > ;
93- public set ( changes : Partial < T > ) : Model < T , C > ;
94- public set < K extends keyof T > ( keyOrChanges : K | Partial < T > , value ?: T [ K ] ) : Model < T , C > {
92+ public set < K extends keyof T > ( key : K , value : T [ K ] ) : Model < T > ;
93+ public set ( changes : Partial < T > ) : Model < T > ;
94+ public set < K extends keyof T > ( keyOrChanges : K | Partial < T > , value ?: T [ K ] ) : Model < T > {
9595 if ( typeof keyOrChanges === "string" ) {
9696 this . data [ keyOrChanges as K ] = value as T [ K ] ;
9797 this . changedFields . add ( keyOrChanges ) ;
@@ -113,9 +113,9 @@ export class Model<T, C = any> {
113113 * @param value - The value to set the field to, if setting a single field. Ignored otherwise.
114114 * @returns The model instance.
115115 */
116- public put < K extends keyof T > ( key : K , value : T [ K ] ) : Model < T , C > ;
117- public put ( changes : Partial < T > ) : Model < T , C > ;
118- public put < K extends keyof T > ( keyOrChanges : K | Partial < T > , value ?: T [ K ] ) : Model < T , C > {
116+ public put < K extends keyof T > ( key : K , value : T [ K ] ) : Model < T > ;
117+ public put ( changes : Partial < T > ) : Model < T > ;
118+ public put < K extends keyof T > ( keyOrChanges : K | Partial < T > , value ?: T [ K ] ) : Model < T > {
119119 if ( typeof keyOrChanges === "string" ) {
120120 this . data [ keyOrChanges as K ] = value as T [ K ] ;
121121 } else {
@@ -142,14 +142,14 @@ export class Model<T, C = any> {
142142 * @param bindValues - Optional array of values to bind to the query if using a SQL string.
143143 * @returns A promise that resolves to an array of matching models.
144144 */
145- public static async all < T , M extends Model < T , C > , C = any > (
146- this : new ( ...args : any [ ] ) => M & Model < T , C > ,
145+ public static async all < T extends ModelAttributes , M extends Model < T > > (
146+ this : new ( ...args : any [ ] ) => M & Model < T > ,
147147 matchOrQuery ?: Partial < T > | string ,
148148 bindValues ?: any [ ]
149149 ) : Promise < M [ ] > {
150- const { adapter, globalSpec } = ( this as unknown as typeof Model < T , C > ) . getPersistence ( ) ;
150+ const { adapter, globalSpec } = ( this as unknown as typeof Model < T > ) . getPersistence ( ) ;
151151 const context = await adapter . getContext ( ) ;
152- const rows = await adapter . all ( context , matchOrQuery as any , bindValues ) ;
152+ const rows = await adapter . all ( context , matchOrQuery , bindValues ) ;
153153 let models = rows . map ( row => ( this as any ) . fromRow ( row ) ) as M [ ] ;
154154 if ( globalSpec ?. postLoad ) {
155155 const promises = models . map < Promise < M > > ( model => globalSpec ?. postLoad ?.( context , model as any ) as Promise < M > ) ;
@@ -164,11 +164,11 @@ export class Model<T, C = any> {
164164 * @param id - The ID of the model to load.
165165 * @returns A promise that resolves to the loaded model, or null if it doesn't exist.
166166 */
167- public static async get < T , M extends Model < T , C > , C = any > (
168- this : new ( ...args : any [ ] ) => M & Model < T , C > ,
167+ public static async get < T extends ModelAttributes , M extends Model < T > > (
168+ this : new ( ...args : any [ ] ) => M & Model < T > ,
169169 id : any
170170 ) : Promise < M | null > {
171- const { adapter, globalSpec } = ( this as unknown as typeof Model < T , C > ) . getPersistence ( ) ;
171+ const { adapter, globalSpec } = ( this as unknown as typeof Model < T > ) . getPersistence ( ) ;
172172 const context = await adapter . getContext ( ) ;
173173 const row = await adapter . get ( context , id ) ;
174174 if ( ! row ) return null ;
@@ -186,12 +186,12 @@ export class Model<T, C = any> {
186186 * @param bindValues - Optional array of values to bind to the query if using a SQL string.
187187 * @returns A promise that resolves to the matching model, or null if none found.
188188 */
189- public static async getBy < T , M extends Model < T , C > , C = any > (
190- this : new ( ...args : any [ ] ) => M & Model < T , C > ,
189+ public static async getBy < T extends ModelAttributes , M extends Model < T > > (
190+ this : new ( ...args : any [ ] ) => M & Model < T > ,
191191 matchOrQuery ?: Partial < T > | string ,
192192 bindValues ?: any [ ]
193193 ) : Promise < M | null > {
194- const { adapter, globalSpec } = ( this as unknown as typeof Model < T , C > ) . getPersistence ( ) ;
194+ const { adapter, globalSpec } = ( this as unknown as typeof Model < T > ) . getPersistence ( ) ;
195195 const context = await adapter . getContext ( ) ;
196196 const row = await adapter . getBy ( context , matchOrQuery as any , bindValues ) ;
197197 if ( ! row ) return null ;
@@ -208,11 +208,11 @@ export class Model<T, C = any> {
208208 * @param row - The row to create the model from.
209209 * @returns The created model.
210210 */
211- protected static fromRow < T , M extends Model < T , C > , C = any > (
212- this : new ( ...args : any [ ] ) => M & Model < T , C > ,
211+ protected static fromRow < T extends ModelAttributes , M extends Model < T > > (
212+ this : new ( ...args : any [ ] ) => Model < T > ,
213213 row : WithId < T >
214214 ) : M {
215- const { fieldSpecs } = ( this as unknown as typeof Model < T , C > ) . getPersistence ( ) ;
215+ const { fieldSpecs } = ( this as unknown as typeof Model < T > ) . getPersistence ( ) ;
216216 const data = { } as any ;
217217 for ( const key in row ) {
218218 const fieldSpec = fieldSpecs ?. [ key ] ;
@@ -222,7 +222,7 @@ export class Model<T, C = any> {
222222 }
223223 }
224224
225- return new this ( data , true ) ;
225+ return new this ( data , true ) as M ;
226226 }
227227
228228 /**
@@ -231,7 +231,7 @@ export class Model<T, C = any> {
231231 * @returns A promise that resolves to the model instance.
232232 */
233233 public async save ( ) : Promise < this> {
234- const { adapter, fieldSpecs, globalSpec } = ( this . constructor as any ) . getPersistence ( ) as PersistenceInfo < T , C > ;
234+ const { adapter, fieldSpecs, globalSpec } = ( this . constructor as any ) . getPersistence ( ) as PersistenceInfo < Model < T > > ;
235235 const fields = this . getChangedFields ( ) . filter ( field => fieldSpecs ?. [ field ] ?. persist !== false ) ;
236236
237237 if ( this . persisted && fields . length === 0 ) return this ;
0 commit comments