11import { OPERATION } from './encoding/spec' ;
22import { DEFAULT_VIEW_TAG , type DefinitionType } from "./annotations" ;
33
4- import { NonFunctionPropNames , ToJSON } from './types/HelperTypes' ;
4+ import { AssignableProps , NonFunctionPropNames , ToJSON } from './types/HelperTypes' ;
55
6- import { ChangeSet , ChangeSetName , ChangeTree , Ref } from './encoder/ChangeTree' ;
6+ import { ChangeSet , ChangeSetName , ChangeTree , IRef , Ref } from './encoder/ChangeTree' ;
77import { $changes , $decoder , $deleteByIndex , $descriptors , $encoder , $filter , $getByIndex , $track } from './types/symbols' ;
88import { StateView } from './encoder/StateView' ;
99
1010import { encodeSchemaOperation } from './encoder/EncodeOperation' ;
1111import { decodeSchemaOperation } from './decoder/DecodeOperation' ;
1212
1313import type { Decoder } from './decoder/Decoder' ;
14- import type { Metadata } from './Metadata' ;
14+ import type { Metadata , MetadataField } from './Metadata' ;
1515import { getIndent } from './utils' ;
1616
1717/**
1818 * Schema encoder / decoder
1919 */
20- export class Schema {
20+ export class Schema < C = any > implements IRef {
21+ static [ Symbol . metadata ] : Metadata ;
2122 static [ $encoder ] = encodeSchemaOperation ;
2223 static [ $decoder ] = decodeSchemaOperation ;
2324
@@ -36,9 +37,7 @@ export class Schema {
3637 }
3738
3839 static is ( type : DefinitionType ) {
39- return typeof ( type [ Symbol . metadata ] ) === "object" ;
40- // const metadata = type[Symbol.metadata];
41- // return metadata && Object.prototype.hasOwnProperty.call(metadata, -1);
40+ return typeof ( ( type as typeof Schema ) [ Symbol . metadata ] ) === "object" ;
4241 }
4342
4443 /**
@@ -58,7 +57,7 @@ export class Schema {
5857 * - Then, the encoder iterates over all "owned" properties per instance and encodes them.
5958 */
6059 static [ $filter ] ( ref : Schema , index : number , view : StateView ) {
61- const metadata : Metadata = ref . constructor [ Symbol . metadata ] ;
60+ const metadata : Metadata = ( ref . constructor as typeof Schema ) [ Symbol . metadata ] ;
6261 const tag = metadata [ index ] ?. tag ;
6362
6463 if ( view === undefined ) {
@@ -81,7 +80,7 @@ export class Schema {
8180 }
8281
8382 // allow inherited classes to have a constructor
84- constructor ( ... args : any [ ] ) {
83+ constructor ( arg ?: C ) {
8584 //
8685 // inline
8786 // Schema.initialize(this);
@@ -91,14 +90,14 @@ export class Schema {
9190 //
9291 // Assign initial values
9392 //
94- if ( args [ 0 ] ) {
95- Object . assign ( this , args [ 0 ] ) ;
93+ if ( arg ) {
94+ Object . assign ( this , arg ) ;
9695 }
9796 }
9897
99- public assign (
100- props : { [ prop in NonFunctionPropNames < this > ] ?: this [ prop ] } | ToJSON < this > ,
101- ) {
98+ public assign < T extends Partial < this > > (
99+ props : AssignableProps < T > ,
100+ ) : this {
102101 Object . assign ( this , props ) ;
103102 return this ;
104103 }
@@ -110,7 +109,7 @@ export class Schema {
110109 * @param operation OPERATION to perform (detected automatically)
111110 */
112111 public setDirty < K extends NonFunctionPropNames < this> > ( property : K | number , operation ?: OPERATION ) {
113- const metadata : Metadata = this . constructor [ Symbol . metadata ] ;
112+ const metadata : Metadata = ( this . constructor as typeof Schema ) [ Symbol . metadata ] ;
114113 this [ $changes ] . change (
115114 metadata [ metadata [ property as string ] ] . index ,
116115 operation
@@ -119,22 +118,21 @@ export class Schema {
119118
120119 clone ( ) : this {
121120 const cloned = new ( ( this as any ) . constructor ) ;
122- const metadata : Metadata = this . constructor [ Symbol . metadata ] ;
121+ const metadata : Metadata = ( this . constructor as typeof Schema ) [ Symbol . metadata ] ;
123122
124123 //
125124 // TODO: clone all properties, not only annotated ones
126125 //
127126 // for (const field in this) {
128127 for ( const fieldIndex in metadata ) {
129- // const field = metadata[metadata[fieldIndex]].name;
130- const field = metadata [ fieldIndex as any as number ] . name ;
128+ const field = metadata [ fieldIndex as any as number ] . name as keyof this;
131129
132130 if (
133131 typeof ( this [ field ] ) === "object" &&
134- typeof ( this [ field ] ?. clone ) === "function"
132+ typeof ( ( this [ field ] as any ) ?. clone ) === "function"
135133 ) {
136134 // deep clone
137- cloned [ field ] = this [ field ] . clone ( ) ;
135+ cloned [ field ] = ( this [ field ] as any ) . clone ( ) ;
138136
139137 } else {
140138 // primitive values
@@ -145,11 +143,11 @@ export class Schema {
145143 return cloned ;
146144 }
147145
148- toJSON ( ) {
149- const obj : unknown = { } ;
146+ toJSON ( this : any ) {
147+ const obj : any = { } ;
150148 const metadata = this . constructor [ Symbol . metadata ] ;
151149 for ( const index in metadata ) {
152- const field = metadata [ index ] ;
150+ const field = metadata [ index ] as MetadataField ;
153151 const fieldName = field . name ;
154152 if ( ! field . deprecated && this [ fieldName ] !== null && typeof ( this [ fieldName ] ) !== "undefined" ) {
155153 obj [ fieldName ] = ( typeof ( this [ fieldName ] [ 'toJSON' ] ) === "function" )
@@ -168,14 +166,14 @@ export class Schema {
168166 this [ $changes ] . discardAll ( ) ;
169167 }
170168
171- protected [ $getByIndex ] ( index : number ) {
172- const metadata : Metadata = this . constructor [ Symbol . metadata ] ;
173- return this [ metadata [ index ] . name ] ;
169+ [ $getByIndex ] ( index : number ) : any {
170+ const metadata : Metadata = ( this . constructor as typeof Schema ) [ Symbol . metadata ] ;
171+ return this [ metadata [ index ] . name as keyof this ] ;
174172 }
175173
176- protected [ $deleteByIndex ] ( index : number ) {
177- const metadata : Metadata = this . constructor [ Symbol . metadata ] ;
178- this [ metadata [ index ] . name ] = undefined ;
174+ [ $deleteByIndex ] ( index : number ) : void {
175+ const metadata : Metadata = ( this . constructor as typeof Schema ) [ Symbol . metadata ] ;
176+ this [ metadata [ index ] . name as keyof this ] = undefined ;
179177 }
180178
181179 /**
@@ -185,7 +183,7 @@ export class Schema {
185183 * @param showContents display JSON contents of the instance
186184 * @returns
187185 */
188- static debugRefIds ( ref : Ref , showContents : boolean = false , level : number = 0 , decoder ?: Decoder , keyPrefix : string = "" ) {
186+ static debugRefIds < T extends Schema > ( ref : T , showContents : boolean = false , level : number = 0 , decoder ?: Decoder , keyPrefix : string = "" ) {
189187 const contents = ( showContents ) ? ` - ${ JSON . stringify ( ref . toJSON ( ) ) } ` : "" ;
190188 const changeTree : ChangeTree = ref [ $changes ] ;
191189
@@ -201,18 +199,18 @@ export class Schema {
201199
202200 changeTree . forEachChild ( ( childChangeTree , indexOrKey ) => {
203201 let key = indexOrKey ;
204- if ( typeof indexOrKey === 'number' && ref [ '$indexes' ] ) {
202+ if ( typeof indexOrKey === 'number' && ( ref as any ) [ '$indexes' ] ) {
205203 // MapSchema
206- key = ref [ '$indexes' ] . get ( indexOrKey ) ?? indexOrKey ;
204+ key = ( ref as any ) [ '$indexes' ] . get ( indexOrKey ) ?? indexOrKey ;
207205 }
208- const keyPrefix = ( ref [ 'forEach' ] !== undefined && key !== undefined ) ? `["${ key } "]: ` : "" ;
206+ const keyPrefix = ( ( ref as any ) [ 'forEach' ] !== undefined && key !== undefined ) ? `["${ key } "]: ` : "" ;
209207 output += this . debugRefIds ( childChangeTree . ref , showContents , level + 1 , decoder , keyPrefix ) ;
210208 } ) ;
211209
212210 return output ;
213211 }
214212
215- static debugRefIdEncodingOrder ( ref : Ref , changeSet : ChangeSetName = 'allChanges' ) {
213+ static debugRefIdEncodingOrder < T extends Ref > ( ref : T , changeSet : ChangeSetName = 'allChanges' ) {
216214 let encodeOrder : number [ ] = [ ] ;
217215 let current = ref [ $changes ] . root [ changeSet ] . next ;
218216 while ( current ) {
@@ -236,7 +234,7 @@ export class Schema {
236234 * @param isEncodeAll Return "full encode" instead of current change set.
237235 * @returns
238236 */
239- static debugChanges ( instance : Ref , isEncodeAll : boolean = false ) {
237+ static debugChanges < T extends Ref > ( instance : T , isEncodeAll : boolean = false ) {
240238 const changeTree : ChangeTree = instance [ $changes ] ;
241239
242240 const changeSet = ( isEncodeAll ) ? changeTree . allChanges : changeTree . changes ;
@@ -278,7 +276,7 @@ export class Schema {
278276 return output ;
279277 }
280278
281- static debugChangesDeep ( ref : Ref , changeSetName : "changes" | "allChanges" | "allFilteredChanges" | "filteredChanges" = "changes" ) {
279+ static debugChangesDeep < T extends Schema > ( ref : T , changeSetName : "changes" | "allChanges" | "allFilteredChanges" | "filteredChanges" = "changes" ) {
282280 let output = "" ;
283281
284282 const rootChangeTree : ChangeTree = ref [ $changes ] ;
@@ -290,7 +288,7 @@ export class Schema {
290288
291289 // TODO: FIXME: this method is not working as expected
292290 for ( const [ refId , changes ] of Object . entries ( root [ changeSetName ] ) ) {
293- const changeTree = root . changeTrees [ refId ] ;
291+ const changeTree = root . changeTrees [ refId as any as number ] ;
294292 if ( ! changeTree ) { continue ; }
295293
296294 let includeChangeTree = false ;
0 commit comments