@@ -200,7 +200,7 @@ export interface CookieOptions {
200200 sameSite ?: string
201201}
202202
203- export class UniversalStorage {
203+ export class UniversalStorage < Data extends Record < string , unknown > > {
204204 private stores : Store [ ]
205205
206206 constructor ( stores ?: Store [ ] ) {
@@ -217,45 +217,56 @@ export class UniversalStorage {
217217 this . stores . push ( store )
218218 }
219219
220- public getAndSync < T > ( key : string , storeTypes ?: StoreType [ ] ) : T | null {
220+ public getAndSync < K extends keyof Data > (
221+ key : string ,
222+ storeTypes ?: StoreType [ ]
223+ ) : Data [ K ] | null {
221224 const val = this . get ( key , storeTypes )
222225
223226 return this . set (
224227 key ,
228+ //@ts -ignore TODO: legacy behavior, getAndSync can change the type of a value from number to string
225229 typeof val === 'number' ? val . toString ( ) : val ,
226230 storeTypes
227- ) as T | null
231+ ) as Data [ K ] | null
228232 }
229233
230- public get < T > ( key : string , storeTypes ?: StoreType [ ] ) : T | null {
234+ public get < K extends keyof Data > (
235+ key : K ,
236+ storeTypes ?: StoreType [ ]
237+ ) : Data [ K ] | null {
231238 let val = null
232239
233240 for ( const store of this . getStores ( storeTypes ) ) {
234- val = store . get < T > ( key )
241+ val = store . get < Data [ K ] > ( key as string )
235242 if ( val ) {
236243 return val
237244 }
238245 }
239246 return null
240247 }
241248
242- public set < T > ( key : string , value : T , storeTypes ?: StoreType [ ] ) : T | null {
249+ public set < K extends keyof Data > (
250+ key : string ,
251+ value : Data [ K ] | null ,
252+ storeTypes ?: StoreType [ ]
253+ ) : Data [ K ] | null {
243254 for ( const store of this . getStores ( storeTypes ) ) {
244255 store . set ( key , value )
245256 }
246257 return value
247258 }
248259
249- public clear ( key : string , storeTypes ?: StoreType [ ] ) : void {
260+ public clear < K extends keyof Data > ( key : K , storeTypes ?: StoreType [ ] ) : void {
250261 for ( const store of this . getStores ( storeTypes ) ) {
251- store . remove ( key )
262+ store . remove ( key as string )
252263 }
253264 }
254265
255- static getUniversalStorage (
266+ static getUniversalStorage < T extends Record < string , unknown > > (
256267 defaultTargets : StoreType [ ] = [ 'cookie' , 'localStorage' , 'memory' ] ,
257268 cookieOptions ?: CookieOptions
258- ) : UniversalStorage {
269+ ) : UniversalStorage < T > {
259270 const stores = [ ]
260271
261272 if ( defaultTargets . includes ( 'cookie' ) && Cookie . available ( ) ) {
@@ -270,7 +281,7 @@ export class UniversalStorage {
270281 stores . push ( new Store ( ) )
271282 }
272283
273- return new UniversalStorage ( stores )
284+ return new UniversalStorage < T > ( stores )
274285 }
275286}
276287
@@ -282,9 +293,21 @@ export class User {
282293 private anonKey : string
283294 private cookieOptions ?: CookieOptions
284295
285- private legacyUserStore : UniversalStorage
286- private traitsStore : UniversalStorage
287- private identityStore : UniversalStorage
296+ private legacyUserStore : UniversalStorage < {
297+ [ k : string ] :
298+ | {
299+ id ?: string
300+ traits ?: Traits
301+ }
302+ | string
303+ } >
304+ private traitsStore : UniversalStorage < {
305+ [ k : string ] : Traits
306+ } >
307+
308+ private identityStore : UniversalStorage < {
309+ [ k : string ] : string
310+ } >
288311
289312 options : UserOptions = { }
290313
@@ -330,11 +353,8 @@ export class User {
330353 cookieOptions
331354 )
332355
333- const legacyUser = this . legacyUserStore . get < {
334- id ?: string
335- traits ?: Traits
336- } > ( defaults . cookie . oldKey )
337- if ( legacyUser ) {
356+ const legacyUser = this . legacyUserStore . get ( defaults . cookie . oldKey )
357+ if ( legacyUser && typeof legacyUser === 'object' ) {
338358 legacyUser . id && this . id ( legacyUser . id )
339359 legacyUser . traits && this . traits ( legacyUser . traits )
340360 }
@@ -357,11 +377,11 @@ export class User {
357377 }
358378 }
359379
360- return (
361- this . identityStore . getAndSync ( this . idKey ) ??
362- this . legacyUserStore . get ( defaults . cookie . oldKey ) ??
363- null
364- )
380+ const retId = this . identityStore . getAndSync ( this . idKey )
381+ if ( retId ) return retId
382+
383+ const retLeg = this . legacyUserStore . get ( defaults . cookie . oldKey )
384+ return retLeg ? ( typeof retLeg === 'object' ? retLeg . id : retLeg ) : null
365385 }
366386
367387 private legacySIO ( ) : [ string , string ] | null {
@@ -380,7 +400,7 @@ export class User {
380400
381401 if ( id === undefined ) {
382402 const val =
383- this . identityStore . getAndSync < ID > ( this . anonKey ) ?? this . legacySIO ( ) ?. [ 0 ]
403+ this . identityStore . getAndSync ( this . anonKey ) ?? this . legacySIO ( ) ?. [ 0 ]
384404
385405 if ( val ) {
386406 return val
0 commit comments