@@ -43,8 +43,8 @@ export const PropertyType = {
4343 ARRAY : 'array' as PropertyType ,
4444} ;
4545
46- export interface Property {
47- name : string ;
46+ export interface Property < T extends { [ key : string ] : any } = any > {
47+ name : keyof T ;
4848 defaultValue ?: any ;
4949 possibleValues ?: any [ ] ;
5050 validate ?: Validator | Validator [ ] ;
@@ -82,8 +82,8 @@ export abstract class BaseImmutable<ValueType, JSType>
8282 // This needs to be defined
8383 // abstract static PROPERTIES: Property[];
8484
85- static jsToValue (
86- properties : Property [ ] ,
85+ static jsToValue < T = any > (
86+ properties : Property < T > [ ] ,
8787 js : any ,
8888 backCompats ?: BackCompat [ ] ,
8989 context ?: Record < string , any > ,
@@ -222,16 +222,16 @@ export abstract class BaseImmutable<ValueType, JSType>
222222 }
223223 }
224224
225- public ownProperties ( ) : Property [ ] {
225+ public ownProperties ( ) : Property < ValueType > [ ] {
226226 return ( this . constructor as any ) . PROPERTIES ;
227227 }
228228
229- public findOwnProperty ( propName : string ) : Property | undefined {
229+ public findOwnProperty ( propName : keyof ValueType ) : Property | undefined {
230230 const properties = this . ownProperties ( ) ;
231231 return NamedArray . findByName ( properties , propName ) ;
232232 }
233233
234- public hasProperty ( propName : string ) : boolean {
234+ public hasProperty ( propName : keyof ValueType ) : boolean {
235235 return this . findOwnProperty ( propName ) !== null ;
236236 }
237237
@@ -319,27 +319,30 @@ export abstract class BaseImmutable<ValueType, JSType>
319319 return true ;
320320 }
321321
322- public get ( propName : string ) : any {
322+ public get < T extends keyof ValueType > ( propName : T ) : ValueType [ T ] {
323323 const getter = ( this as any ) [ 'get' + firstUp ( propName ) ] ;
324324 if ( ! getter ) throw new Error ( `can not find prop ${ propName } ` ) ;
325325 return getter . call ( this ) ;
326326 }
327327
328- public change ( propName : string , newValue : any ) : this {
328+ public change < T extends keyof ValueType > ( propName : T , newValue : ValueType [ T ] ) : this {
329329 const changer = ( this as any ) [ 'change' + firstUp ( propName ) ] ;
330330 if ( ! changer ) throw new Error ( `can not find prop ${ propName } ` ) ;
331331 return changer . call ( this , newValue ) ;
332332 }
333333
334- public changeMany ( properties : Record < string , any > ) : this {
334+ public changeMany ( properties : Partial < ValueType > ) : this {
335335 if ( ! properties ) throw new TypeError ( 'Invalid properties object' ) ;
336336
337337 let o = this ;
338338
339339 for ( const propName in properties ) {
340340 if ( ! this . hasProperty ( propName ) ) throw new Error ( 'Unknown property: ' + propName ) ;
341341
342- o = o . change ( propName , properties [ propName ] ) ;
342+ // Added ! because TypeScript thinks a Partial can have undefined properties
343+ // (which they can and it's cool)
344+ // https://github.com/Microsoft/TypeScript/issues/13195
345+ o = o . change ( propName , properties [ propName ] ! ) ;
343346 }
344347
345348 return o ;
0 commit comments