Skip to content

Commit c17e5fc

Browse files
committed
better typing for UniversalStorage
1 parent 3358219 commit c17e5fc

File tree

3 files changed

+53
-32
lines changed

3 files changed

+53
-32
lines changed

packages/browser/src/core/analytics/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ export class Analytics
9898
private _group: Group
9999
private eventFactory: EventFactory
100100
private _debug = false
101-
private _universalStorage: UniversalStorage
101+
private _universalStorage: UniversalStorage<{
102+
[k: string]: unknown
103+
}>
102104

103105
initialized = false
104106
integrations: Integrations

packages/browser/src/core/user/index.ts

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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

packages/browser/src/plugins/segmentio/normalize.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,14 @@ function referrerId(
9595
ctx: SegmentEvent['context'],
9696
disablePersistance: boolean
9797
): void {
98-
const storage = UniversalStorage.getUniversalStorage(
99-
['cookie'],
100-
getCookieOptions()
101-
)
98+
const storage = UniversalStorage.getUniversalStorage<{
99+
's:context.referrer': Ad
100+
}>(['cookie'], getCookieOptions())
102101

103102
const stored = storage.get('s:context.referrer', ['cookie'])
104-
let ad = ads(query)
103+
let ad: Ad | undefined | null = ads(query)
105104

106-
ad = ad ?? (stored as Ad | undefined)
105+
ad = ad ?? stored
107106

108107
if (!ad) {
109108
return

0 commit comments

Comments
 (0)