@revolugo/common 7.13.0 → 7.13.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/types/elements/elements-events.ts +3 -6
- package/src/types/elements/hotel-room-offer.ts +3 -3
- package/src/utils/case-transformers.ts +21 -19
- package/src/utils/debounce.ts +17 -28
- package/src/utils/defaults-deep.ts +10 -14
- package/src/utils/omit.ts +5 -6
- package/src/utils/poller.ts +31 -23
- package/src/utils/shake.ts +14 -11
package/package.json
CHANGED
|
@@ -50,11 +50,9 @@ export enum ElementsEvent {
|
|
|
50
50
|
export interface ElementsEventCallbacks {
|
|
51
51
|
[ElementsEvent.BookingCreated]: Booking
|
|
52
52
|
[ElementsEvent.BookingFlowStepUpdated]: BookingState
|
|
53
|
-
|
|
54
|
-
[ElementsEvent.BookingManagerNewBooking]: any
|
|
53
|
+
[ElementsEvent.BookingManagerNewBooking]: undefined
|
|
55
54
|
[ElementsEvent.BookingManagerRetrieve]: Booking
|
|
56
|
-
|
|
57
|
-
[ElementsEvent.BookingManagerRetrieveFail]: any
|
|
55
|
+
[ElementsEvent.BookingManagerRetrieveFail]: undefined
|
|
58
56
|
[ElementsEvent.BookingPolicyCreated]: BookingPolicies
|
|
59
57
|
[ElementsEvent.CancellationPoliciesUpdated]: CancellationPolicy[]
|
|
60
58
|
[ElementsEvent.CurrencyUpdated]: CurrencyType
|
|
@@ -67,8 +65,7 @@ export interface ElementsEventCallbacks {
|
|
|
67
65
|
[ElementsEvent.HotelOffersItemClick]: HotelOffer | [HotelOffer, number]
|
|
68
66
|
[ElementsEvent.HotelOffersMarkerClick]: HotelOffer | [HotelOffer, number]
|
|
69
67
|
[ElementsEvent.HotelOffersOpenInNewTabClick]: string
|
|
70
|
-
|
|
71
|
-
[ElementsEvent.HotelOffersPollingStarted]: any
|
|
68
|
+
[ElementsEvent.HotelOffersPollingStarted]: undefined
|
|
72
69
|
[ElementsEvent.HotelOffersRetrieved]: HotelOffer[]
|
|
73
70
|
[ElementsEvent.HotelRetrieved]: Hotel
|
|
74
71
|
[ElementsEvent.HotelRoomOfferItemVisible]: [HotelRoomOffer, number]
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CancellationPolicy } from './cancellation-policy.ts'
|
|
2
2
|
import type { CurrencyType } from './currency.ts'
|
|
3
|
+
import type { Event } from './event.ts'
|
|
3
4
|
import type { HotelRoomOfferPackageType } from './hotel-room-offer-package-type.ts'
|
|
4
5
|
import type { HotelRoomOfferType } from './hotel-room-offer-type.ts'
|
|
5
6
|
import type { HotelRoom } from './hotel-room.ts'
|
|
@@ -219,11 +220,10 @@ export interface HotelRoomOffersResponse {
|
|
|
219
220
|
data: HotelRoomOffersDataResponse
|
|
220
221
|
/**
|
|
221
222
|
*
|
|
222
|
-
* @type {
|
|
223
|
+
* @type {Event}
|
|
223
224
|
* @memberof HotelRoomOffersApiResponse
|
|
224
225
|
*/
|
|
225
|
-
|
|
226
|
-
event?: any | null
|
|
226
|
+
event?: Event | null
|
|
227
227
|
/**
|
|
228
228
|
*
|
|
229
229
|
* @type {MetaApiPollingResponse}
|
|
@@ -53,34 +53,37 @@ function matches(patterns: (RegExp | string)[], value: string) {
|
|
|
53
53
|
)
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
type PlainObject = Record<string, unknown>
|
|
57
|
+
|
|
58
|
+
function isPlainObject(value: unknown): value is PlainObject {
|
|
59
|
+
return (
|
|
60
|
+
value === Object(value) &&
|
|
61
|
+
!Array.isArray(value) &&
|
|
62
|
+
typeof value !== 'function'
|
|
63
|
+
)
|
|
58
64
|
}
|
|
59
65
|
|
|
60
|
-
|
|
61
|
-
export function keysChangeCase<T
|
|
62
|
-
obj:
|
|
66
|
+
/** Infer `T` from input, or set `T` explicitly when output type differs (e.g. fixture → domain). */
|
|
67
|
+
export function keysChangeCase<T extends object | readonly unknown[]>(
|
|
68
|
+
obj: T | object | readonly unknown[],
|
|
63
69
|
toCase: CaseTransformer,
|
|
64
|
-
|
|
65
70
|
options?: { deep?: boolean; exclude?: (RegExp | string)[] },
|
|
66
|
-
): T
|
|
71
|
+
): T
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
export function keysChangeCase
|
|
73
|
+
/** Unknown input — `Record<string, unknown>` / `unknown[]` instead of `unknown`. */
|
|
74
|
+
export function keysChangeCase(
|
|
70
75
|
obj: unknown,
|
|
71
76
|
toCase: CaseTransformer,
|
|
72
77
|
options?: { deep?: boolean; exclude?: (RegExp | string)[] },
|
|
73
|
-
):
|
|
78
|
+
): PlainObject | unknown[]
|
|
74
79
|
|
|
75
|
-
export function keysChangeCase
|
|
76
|
-
|
|
77
|
-
obj: any,
|
|
80
|
+
export function keysChangeCase(
|
|
81
|
+
obj: unknown,
|
|
78
82
|
toCase: CaseTransformer,
|
|
79
|
-
|
|
80
83
|
options: { deep?: boolean; exclude?: (RegExp | string)[] } = { deep: true },
|
|
81
|
-
): unknown {
|
|
82
|
-
if (
|
|
83
|
-
return Object.keys(obj).reduce<
|
|
84
|
+
): PlainObject | unknown[] | unknown {
|
|
85
|
+
if (isPlainObject(obj) && !(obj instanceof Date)) {
|
|
86
|
+
return Object.keys(obj).reduce<PlainObject>((result, key) => {
|
|
84
87
|
// Check if key should be excluded from the transformation
|
|
85
88
|
const transformedKey =
|
|
86
89
|
options?.exclude && matches(options.exclude, key)
|
|
@@ -94,12 +97,11 @@ export function keysChangeCase<T>(
|
|
|
94
97
|
return result
|
|
95
98
|
}, {})
|
|
96
99
|
} else if (Array.isArray(obj)) {
|
|
97
|
-
return obj.map(item => keysChangeCase(item, toCase, options))
|
|
100
|
+
return obj.map(item => keysChangeCase(item, toCase, options))
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
return obj
|
|
101
104
|
}
|
|
102
|
-
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
103
105
|
|
|
104
106
|
export function capitalize(value: string): string {
|
|
105
107
|
return value.replace(/^\w/u, c => c.toUpperCase())
|
package/src/utils/debounce.ts
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
1
|
interface Options<Result> {
|
|
3
2
|
isImmediate?: boolean
|
|
4
3
|
maxWait?: number
|
|
5
4
|
callback?: (data: Result) => void
|
|
6
5
|
}
|
|
7
6
|
|
|
8
|
-
export interface DebouncedFunction<
|
|
9
|
-
Args
|
|
10
|
-
F extends (...args: Args) => any,
|
|
11
|
-
> {
|
|
12
|
-
(
|
|
13
|
-
this: ThisParameterType<F>,
|
|
14
|
-
...args: Args & Parameters<F>
|
|
15
|
-
): Promise<Awaited<ReturnType<F>>>
|
|
7
|
+
export interface DebouncedFunction<Args extends unknown[], Return> {
|
|
8
|
+
(...args: Args): Promise<Awaited<Return>>
|
|
16
9
|
cancel: (reason?: unknown) => void
|
|
17
10
|
}
|
|
18
11
|
|
|
@@ -21,18 +14,18 @@ interface DebouncedPromise<FunctionReturn> {
|
|
|
21
14
|
resolve: (result: FunctionReturn) => void
|
|
22
15
|
}
|
|
23
16
|
|
|
24
|
-
export function debounce<Args extends
|
|
25
|
-
func:
|
|
17
|
+
export function debounce<Args extends unknown[], Return>(
|
|
18
|
+
func: (...args: Args) => Return,
|
|
26
19
|
waitMilliseconds = 50,
|
|
27
|
-
options: Options<Awaited<
|
|
28
|
-
): DebouncedFunction<Args,
|
|
20
|
+
options: Options<Awaited<Return>> = {},
|
|
21
|
+
): DebouncedFunction<Args, Return> {
|
|
29
22
|
let timeoutId: ReturnType<typeof setTimeout> | undefined = undefined
|
|
30
23
|
const isImmediate = options.isImmediate ?? false
|
|
31
24
|
const callback = options.callback ?? false
|
|
32
25
|
const { maxWait } = options
|
|
33
26
|
let lastInvokeTime = Date.now()
|
|
34
27
|
|
|
35
|
-
let promises: DebouncedPromise<
|
|
28
|
+
let promises: DebouncedPromise<Awaited<Return>>[] = []
|
|
36
29
|
|
|
37
30
|
function nextInvokeTimeout() {
|
|
38
31
|
if (maxWait !== undefined) {
|
|
@@ -46,22 +39,19 @@ export function debounce<Args extends any[], F extends (...args: Args) => any>(
|
|
|
46
39
|
return waitMilliseconds
|
|
47
40
|
}
|
|
48
41
|
|
|
49
|
-
function debouncedFunction(
|
|
50
|
-
this: ThisParameterType<F>,
|
|
51
|
-
...args: Parameters<F>
|
|
52
|
-
) {
|
|
53
|
-
// eslint-disable-next-line consistent-this, @typescript-eslint/no-this-alias
|
|
54
|
-
const context = this
|
|
42
|
+
function debouncedFunction(...args: Args) {
|
|
55
43
|
// eslint-disable-next-line consistent-return
|
|
56
|
-
return new Promise<Awaited<
|
|
44
|
+
return new Promise<Awaited<Return>>((resolve, reject) => {
|
|
57
45
|
function invokeFunction() {
|
|
58
46
|
timeoutId = undefined
|
|
59
47
|
lastInvokeTime = Date.now()
|
|
60
48
|
if (!isImmediate) {
|
|
61
|
-
const result = func
|
|
49
|
+
const result = func(...args)
|
|
62
50
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
63
|
-
callback && callback(result)
|
|
64
|
-
promises.forEach(({ resolve: resolveLoop }) =>
|
|
51
|
+
callback && callback(result as Awaited<Return>)
|
|
52
|
+
promises.forEach(({ resolve: resolveLoop }) =>
|
|
53
|
+
resolveLoop(result as Awaited<Return>),
|
|
54
|
+
)
|
|
65
55
|
promises = []
|
|
66
56
|
}
|
|
67
57
|
}
|
|
@@ -75,11 +65,11 @@ export function debounce<Args extends any[], F extends (...args: Args) => any>(
|
|
|
75
65
|
timeoutId = setTimeout(invokeFunction, nextInvokeTimeout())
|
|
76
66
|
|
|
77
67
|
if (shouldCallNow) {
|
|
78
|
-
const result = func
|
|
68
|
+
const result = func(...args)
|
|
79
69
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
80
|
-
callback && callback(result)
|
|
70
|
+
callback && callback(result as Awaited<Return>)
|
|
81
71
|
// eslint-disable-next-line no-promise-executor-return
|
|
82
|
-
return resolve(result)
|
|
72
|
+
return resolve(result as Awaited<Return>)
|
|
83
73
|
}
|
|
84
74
|
promises.push({ reject, resolve })
|
|
85
75
|
})
|
|
@@ -95,4 +85,3 @@ export function debounce<Args extends any[], F extends (...args: Args) => any>(
|
|
|
95
85
|
|
|
96
86
|
return debouncedFunction
|
|
97
87
|
}
|
|
98
|
-
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
@@ -11,26 +11,22 @@
|
|
|
11
11
|
* - Avoids infinite recursion for circular source structures.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
type AnyObject = Record<string, any>
|
|
14
|
+
type PlainObject = Record<string, unknown>
|
|
16
15
|
|
|
17
|
-
function isObject(value:
|
|
16
|
+
function isObject(value: unknown): value is PlainObject {
|
|
18
17
|
return value !== null && typeof value === 'object'
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
export function defaultsDeep<T>(
|
|
22
|
-
object: T,
|
|
23
|
-
...sources: any[]
|
|
24
|
-
): T extends AnyObject ? T : any {
|
|
20
|
+
export function defaultsDeep<T>(object: T, ...sources: unknown[]): T {
|
|
25
21
|
// Ensure we always return an object reference we can mutate (lodash creates/uses {} when target is falsy)
|
|
26
|
-
const target:
|
|
22
|
+
const target: PlainObject = (
|
|
27
23
|
object === null || object === undefined ? {} : object
|
|
28
|
-
) as
|
|
24
|
+
) as PlainObject
|
|
29
25
|
|
|
30
26
|
// WeakMap to track already-cloned source objects so circular refs won't blow the stack
|
|
31
27
|
const seen = new WeakMap<object, object>()
|
|
32
28
|
|
|
33
|
-
function applyDefaults(dst:
|
|
29
|
+
function applyDefaults(dst: PlainObject, src: PlainObject) {
|
|
34
30
|
// Only iterate string-keyed enumerable properties (own + inherited) => for...in
|
|
35
31
|
for (const key in src) {
|
|
36
32
|
if (Object.hasOwn(src, key)) {
|
|
@@ -49,12 +45,12 @@ export function defaultsDeep<T>(
|
|
|
49
45
|
// Prepare new container (array vs object)
|
|
50
46
|
const created = Array.isArray(srcVal)
|
|
51
47
|
? ([] as unknown[])
|
|
52
|
-
: ({} as
|
|
48
|
+
: ({} as PlainObject)
|
|
53
49
|
// remember mapping to handle circular refs
|
|
54
50
|
seen.set(srcVal, created)
|
|
55
51
|
|
|
56
52
|
// Recursively fill created from srcVal
|
|
57
|
-
applyDefaults(created, srcVal)
|
|
53
|
+
applyDefaults(created as PlainObject, srcVal)
|
|
58
54
|
|
|
59
55
|
// assign the created clone as the default
|
|
60
56
|
dst[key] = created
|
|
@@ -75,11 +71,11 @@ export function defaultsDeep<T>(
|
|
|
75
71
|
}
|
|
76
72
|
|
|
77
73
|
for (const src of sources) {
|
|
78
|
-
if (src
|
|
74
|
+
if (isObject(src)) {
|
|
79
75
|
// If source itself has been seen (unlikely across top-level sources), we still traverse it
|
|
80
76
|
applyDefaults(target, src)
|
|
81
77
|
}
|
|
82
78
|
}
|
|
83
79
|
|
|
84
|
-
return target as
|
|
80
|
+
return target as T
|
|
85
81
|
}
|
package/src/utils/omit.ts
CHANGED
|
@@ -10,8 +10,8 @@ export function omit<T extends object, K extends keyof T>(
|
|
|
10
10
|
// eslint-disable-next-line no-restricted-syntax
|
|
11
11
|
): Omit<T, K> {
|
|
12
12
|
if (object === null || object === undefined) {
|
|
13
|
-
// eslint-disable-next-line
|
|
14
|
-
return {} as
|
|
13
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
14
|
+
return {} as Omit<T, K>
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const keysArray = (
|
|
@@ -24,16 +24,15 @@ export function omit<T extends object, K extends keyof T>(
|
|
|
24
24
|
// Copy string/number keys
|
|
25
25
|
for (const key in object) {
|
|
26
26
|
if (Object.hasOwn(object, key) && !keysSet.has(key as keyof T)) {
|
|
27
|
-
|
|
28
|
-
;(result as any)[key] = object[key as keyof T]
|
|
27
|
+
result[key as keyof T] = object[key as keyof T]
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
// Copy symbol keys
|
|
32
|
+
const record = object as T & Record<PropertyKey, T[keyof T]>
|
|
33
33
|
for (const sym of Object.getOwnPropertySymbols(object)) {
|
|
34
34
|
if (!keysSet.has(sym as keyof T)) {
|
|
35
|
-
|
|
36
|
-
;(result as any)[sym as unknown as keyof T] = (object as any)[sym]
|
|
35
|
+
result[sym as keyof T] = record[sym]
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
38
|
|
package/src/utils/poller.ts
CHANGED
|
@@ -2,8 +2,7 @@ import { v4 as uuidv4 } from 'uuid'
|
|
|
2
2
|
|
|
3
3
|
import { CaseTransformer, keysChangeCase } from './case-transformers.ts'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
export interface IPollerResponse<T = any> {
|
|
5
|
+
export interface IPollerResponse<T = unknown> {
|
|
7
6
|
data?: T
|
|
8
7
|
meta?: {
|
|
9
8
|
status: 'COMPLETE' | 'IN_PROGRESS'
|
|
@@ -23,6 +22,20 @@ export type TPollerEvents<V extends IPollerResponse = IPollerResponse> = {
|
|
|
23
22
|
|
|
24
23
|
const INTERVAL = 1500
|
|
25
24
|
|
|
25
|
+
function omitUndefined<T extends object>(obj: T): Partial<T> {
|
|
26
|
+
const out: Partial<T> = {}
|
|
27
|
+
|
|
28
|
+
for (const key of Object.keys(obj) as (keyof T)[]) {
|
|
29
|
+
const value = obj[key]
|
|
30
|
+
|
|
31
|
+
if (value !== undefined) {
|
|
32
|
+
out[key] = value
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return out
|
|
37
|
+
}
|
|
38
|
+
|
|
26
39
|
export interface IPollerOptions<U> {
|
|
27
40
|
callCount?: number
|
|
28
41
|
interval?: number
|
|
@@ -76,7 +89,10 @@ export class Poller<V extends IPollerResponse> {
|
|
|
76
89
|
request()
|
|
77
90
|
.then(result => this.onRequest(result, request, buildedOptions))
|
|
78
91
|
.catch((error: unknown) => {
|
|
79
|
-
|
|
92
|
+
const payload =
|
|
93
|
+
error instanceof Error ? error : new Error(String(error))
|
|
94
|
+
|
|
95
|
+
this.dispatch('error', payload)
|
|
80
96
|
})
|
|
81
97
|
}
|
|
82
98
|
|
|
@@ -91,21 +107,9 @@ export class Poller<V extends IPollerResponse> {
|
|
|
91
107
|
}
|
|
92
108
|
|
|
93
109
|
private buildPollerOptions(options: TOptions<V>): TOptions<V> {
|
|
94
|
-
const compactedOptions = Object.entries(options).reduce<
|
|
95
|
-
Record<string, unknown>
|
|
96
|
-
>((acc, [key, value]) => {
|
|
97
|
-
if (value !== undefined) {
|
|
98
|
-
const tKey = key as keyof TOptions<V>
|
|
99
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
100
|
-
acc[tKey] = value as any
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return acc
|
|
104
|
-
}, {}) as TOptions<V>
|
|
105
|
-
|
|
106
110
|
return {
|
|
107
111
|
...this.defaultOptions,
|
|
108
|
-
...
|
|
112
|
+
...omitUndefined(options),
|
|
109
113
|
}
|
|
110
114
|
}
|
|
111
115
|
|
|
@@ -142,7 +146,7 @@ export class Poller<V extends IPollerResponse> {
|
|
|
142
146
|
request: TRequest<V>,
|
|
143
147
|
options: TOptions<V>,
|
|
144
148
|
): Promise<void> {
|
|
145
|
-
const resultFormatted = keysChangeCase(result
|
|
149
|
+
const resultFormatted = keysChangeCase<V>(result, CaseTransformer.Camel)
|
|
146
150
|
|
|
147
151
|
if (!this.isActivePoller(options)) {
|
|
148
152
|
return
|
|
@@ -161,8 +165,10 @@ export class Poller<V extends IPollerResponse> {
|
|
|
161
165
|
) {
|
|
162
166
|
// If not in progress but still need to meet minimum call count, set status to in progress
|
|
163
167
|
if (!this.isInProgress(resultFormatted)) {
|
|
164
|
-
resultFormatted.meta =
|
|
165
|
-
|
|
168
|
+
resultFormatted.meta = {
|
|
169
|
+
...resultFormatted.meta,
|
|
170
|
+
status: 'IN_PROGRESS',
|
|
171
|
+
}
|
|
166
172
|
}
|
|
167
173
|
|
|
168
174
|
// Increment call count and dispatch data
|
|
@@ -180,8 +186,10 @@ export class Poller<V extends IPollerResponse> {
|
|
|
180
186
|
// Handle the case when polling should complete
|
|
181
187
|
} else if (this.isInProgress(resultFormatted)) {
|
|
182
188
|
// Mark as complete if it was in progress
|
|
183
|
-
resultFormatted.meta =
|
|
184
|
-
|
|
189
|
+
resultFormatted.meta = {
|
|
190
|
+
...resultFormatted.meta,
|
|
191
|
+
status: 'COMPLETE',
|
|
192
|
+
}
|
|
185
193
|
this.onComplete(resultFormatted, options)
|
|
186
194
|
// Handle the case when already complete
|
|
187
195
|
} else {
|
|
@@ -221,8 +229,8 @@ export type TPollerCallback<T extends IPollerResponse = IPollerResponse> = (
|
|
|
221
229
|
export function pollRequest<R extends IPollerResponse>(
|
|
222
230
|
request: TRequest<R>,
|
|
223
231
|
options: TOptions<R>,
|
|
224
|
-
pollerCallback: TPollerCallback
|
|
225
|
-
): Promise<PollerReturn
|
|
232
|
+
pollerCallback: TPollerCallback<R>,
|
|
233
|
+
): Promise<PollerReturn<R>>
|
|
226
234
|
|
|
227
235
|
export function pollRequest<R extends IPollerResponse>(
|
|
228
236
|
request: TRequest<R>,
|
package/src/utils/shake.ts
CHANGED
|
@@ -4,21 +4,24 @@
|
|
|
4
4
|
* by custom evaluation.
|
|
5
5
|
*/
|
|
6
6
|
// eslint-disable-next-line no-restricted-syntax
|
|
7
|
-
export function shake<RemovedKeys extends string, T>(
|
|
7
|
+
export function shake<RemovedKeys extends string, T extends object>(
|
|
8
8
|
obj: T,
|
|
9
|
-
|
|
10
|
-
filter: (value: any) => boolean = x => x === undefined,
|
|
9
|
+
filter: (value: unknown) => boolean = x => x === undefined,
|
|
11
10
|
// eslint-disable-next-line no-restricted-syntax
|
|
12
11
|
): Omit<T, RemovedKeys> {
|
|
13
12
|
if (!obj) {
|
|
14
|
-
|
|
13
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
14
|
+
return {} as Omit<T, RemovedKeys>
|
|
15
15
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
|
|
17
|
+
const result: Partial<T> = {}
|
|
18
|
+
|
|
19
|
+
for (const key of Object.keys(obj) as (keyof T)[]) {
|
|
20
|
+
if (!filter(obj[key])) {
|
|
21
|
+
result[key] = obj[key]
|
|
20
22
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
26
|
+
return result as Omit<T, RemovedKeys>
|
|
24
27
|
}
|