@@ -3,6 +3,7 @@ import { find } from 'ramda';
33const sDefinition = Symbol ( 'definition' ) ;
44const RUNTIME = {
55 usingFactory : false ,
6+ prefixCache : new Map ( ) ,
67} ;
78
89function factory < T > (
@@ -13,7 +14,7 @@ function factory<T>(
1314 const baseFunction = descriptor . value ;
1415 return {
1516 ...descriptor ,
16- value ( this : ThisType < T > , ...args ) {
17+ value ( this : ThisType < T > , ...args : any ) {
1718 RUNTIME . usingFactory = true ;
1819 const result = baseFunction . call ( this , ...args ) ;
1920 RUNTIME . usingFactory = false ;
@@ -22,13 +23,13 @@ function factory<T>(
2223 } ;
2324}
2425
25- export type ObjectMapKey < D > = D extends ObjectMap < infer K , infer V , infer T > &
26- infer T
26+ export type ObjectMapKey < D > = D extends ObjectMap < infer D , infer K , infer V > &
27+ infer D
2728 ? K
2829 : never ;
2930
30- export type ObjectMapValue < D > = D extends ObjectMap < infer K , infer V , infer T > &
31- infer T
31+ export type ObjectMapValue < D > = D extends ObjectMap < infer D , infer K , infer V > &
32+ infer D
3233 ? V
3334 : never ;
3435
@@ -37,13 +38,13 @@ export function prefixString(str: string, prefix: string = ''): string {
3738}
3839
3940export class ObjectMap <
40- K extends keyof T ,
41- V extends T [ K ] ,
42- T extends Record < string | number , any >
41+ D extends Record < string | number , any > ,
42+ K extends keyof D ,
43+ V extends D [ K ]
4344> {
4445 private readonly [ sDefinition ] = new Map ( ) ;
4546
46- constructor ( definition : T ) {
47+ constructor ( definition : D ) {
4748 if ( ! RUNTIME . usingFactory ) {
4849 throw TypeError (
4950 'Instantiating ObjectMap with `new ObjectMap(definition)` is not recommended. ' +
@@ -67,42 +68,39 @@ export class ObjectMap<
6768
6869 @factory
6970 static fromObject <
70- K extends keyof T ,
71- V extends T [ K ] ,
72- T extends Record < string | number , any >
73- > ( definition : T ) {
74- return new ObjectMap ( definition ) as ObjectMap < K , V , T > & T ;
71+ D extends Record < string | number , any > ,
72+ K extends keyof D ,
73+ V extends D [ K ]
74+ > ( definition : D ) {
75+ return new ObjectMap ( definition ) as ObjectMap < D , K , V > & D ;
7576 }
7677
7778 @factory
78- static fromKeys < T extends string > ( keys : T [ ] ) {
79- const definition = { } as Record < T , T > ;
79+ static fromKeys < K extends string > ( keys : K [ ] ) {
80+ const definition = { } as Record < K , K > ;
8081 for ( const key of keys ) {
8182 definition [ key ] = key ;
8283 }
83- return new ObjectMap ( definition ) as ObjectMap < T , T , { [ K in T ] : K } > &
84- { [ K in T ] : K } ;
84+ return new ObjectMap ( definition ) as ObjectMap < { [ V in K ] : V } , K , K > &
85+ { [ V in K ] : V } ;
8586 }
8687
8788 @factory
88- static prefixKeys < T extends string , K extends T > (
89- keys : K [ ] ,
90- prefix : string = '' ,
91- ) {
89+ static prefixKeys < K extends string > ( keys : K [ ] , prefix : string = '' ) {
9290 const definition = { } as Record < K , string > ;
9391 for ( const key of keys ) {
9492 definition [ key ] = prefixString ( key , prefix ) ;
9593 }
9694 return new ObjectMap ( definition ) as ObjectMap <
95+ { [ V in K ] : string } ,
9796 K ,
98- string ,
99- { [ V in K ] : string }
97+ string
10098 > &
10199 { [ V in K ] : string } ;
102100 }
103101
104- static getKey < K extends keyof T , V extends T [ K ] , T > (
105- instance : ObjectMap < K , V , T > & T ,
102+ static getKey < D , K extends keyof D , V extends D [ K ] > (
103+ instance : ObjectMap < D , K , V > & D ,
106104 value : V ,
107105 ) : K {
108106 const [ key = null ] =
@@ -111,48 +109,75 @@ export class ObjectMap<
111109 return key ;
112110 }
113111
114- static entries < K extends keyof T , V extends T [ K ] , T > (
115- instance : ObjectMap < K , V , T > & T ,
112+ static entries < D , K extends keyof D , V extends D [ K ] > (
113+ instance : ObjectMap < D , K , V > & D ,
116114 ) : IterableIterator < [ K , V ] > {
117115 return instance [ sDefinition ] . entries ( ) ;
118116 }
119117
120- static size < K extends keyof T , V extends T [ K ] , T > (
121- instance : ObjectMap < K , V , T > & T ,
118+ static size < K extends keyof D , V extends D [ K ] , D > (
119+ instance : ObjectMap < D , K , V > & D ,
122120 ) : number {
123121 return instance [ sDefinition ] . size ;
124122 }
125123
126- static has < K extends keyof T , V extends T [ K ] , T > (
127- instance : ObjectMap < K , V , T > & T ,
124+ static has < K extends keyof D , V extends D [ K ] , D > (
125+ instance : ObjectMap < D , K , V > & D ,
128126 key : K ,
129127 ) : boolean {
130128 return instance [ sDefinition ] . has ( key ) ;
131129 }
132130
133- static hasValue < K extends keyof T , V extends T [ K ] , T > (
134- instance : ObjectMap < K , V , T > & T ,
131+ static hasValue < D , K extends keyof D , V extends D [ K ] > (
132+ instance : ObjectMap < D , K , V > & D ,
135133 value : V ,
136134 ) : boolean {
137135 return ! ! ObjectMap . getKey ( instance , value ) ;
138136 }
139137
140- static keys < K extends keyof T , V extends T [ K ] , T > (
141- instance : ObjectMap < K , V , T > & T ,
138+ static keys < D , K extends keyof D , V extends D [ K ] > (
139+ instance : ObjectMap < D , K , V > & D ,
142140 ) : IterableIterator < K > {
143141 return instance [ sDefinition ] . keys ( ) ;
144142 }
145143
146- static values < K extends keyof T , V extends T [ K ] , T > (
147- instance : ObjectMap < K , V , T > & T ,
144+ static values < D , K extends keyof D , V extends D [ K ] > (
145+ instance : ObjectMap < D , K , V > & D ,
148146 ) : IterableIterator < V > {
149147 return instance [ sDefinition ] . values ( ) ;
150148 }
151149
152- static forEach < K extends keyof T , V extends T [ K ] , T > (
153- fn : ( value : V , key : K , map : ObjectMap < K , V , T > & T ) => void ,
154- instance : ObjectMap < K , V , T > & T ,
150+ static forEach < D , K extends keyof D , V extends D [ K ] > (
151+ fn : ( value : V , key : K , map : ObjectMap < D , K , V > & D ) => void ,
152+ instance : ObjectMap < D , K , V > & D ,
155153 ) : void {
156154 return instance [ sDefinition ] . forEach ( ( v , k ) => fn ( v , k , instance ) ) ;
157155 }
156+
157+ static prefixValues <
158+ D extends Record < K , string > ,
159+ K extends keyof D ,
160+ V extends D [ K ]
161+ > ( instance : ObjectMap < D , K , V > & D , prefix = '' ) {
162+ if ( prefix === '' ) {
163+ return instance ;
164+ }
165+ if ( ! RUNTIME . prefixCache . has ( prefix ) ) {
166+ RUNTIME . prefixCache . set ( prefix , new Map ( ) ) ;
167+ }
168+ if ( ! RUNTIME . prefixCache . get ( prefix ) . has ( instance ) ) {
169+ const definition = { } as Record < K , string > ;
170+ ObjectMap . forEach ( ( value , key ) => {
171+ definition [ key ] = prefixString ( value , prefix ) ;
172+ } , instance ) ;
173+ const prefixedInstance = ObjectMap . fromObject ( definition ) ;
174+ RUNTIME . prefixCache . get ( prefix ) . set ( instance , prefixedInstance ) ;
175+ }
176+ return RUNTIME . prefixCache . get ( prefix ) . get ( instance ) as ObjectMap <
177+ { [ V in K ] : string } ,
178+ K ,
179+ string
180+ > &
181+ { [ V in K ] : string } ;
182+ }
158183}
0 commit comments