feat: add pruneEmptyDeep; improve omit types

pull/659/head
Travis Fischer 2024-08-01 01:41:36 -05:00
rodzic 08012e28a9
commit 84544c774c
3 zmienionych plików z 118 dodań i 11 usunięć

Wyświetl plik

@ -6,6 +6,8 @@ import { mockKyInstance } from './_utils'
import {
omit,
pick,
pruneEmpty,
pruneEmptyDeep,
sanitizeSearchParams,
stringifyForModel,
throttleKy
@ -20,9 +22,11 @@ test('pick', () => {
test('omit', () => {
expect(omit({ a: 1, b: 2, c: 3 }, 'a', 'c')).toEqual({ b: 2 })
expect(
omit({ a: { b: 'foo' }, d: -1, foo: null } as any, 'b', 'foo')
).toEqual({ a: { b: 'foo' }, d: -1 })
expect(omit({ a: { b: 'foo' }, d: -1, foo: null }, 'b', 'foo')).toEqual({
a: { b: 'foo' },
d: -1
})
expect(omit({ a: 1, b: 2, c: 3 }, 'foo', 'bar', 'c')).toEqual({ a: 1, b: 2 })
})
test('sanitizeSearchParams', () => {
@ -71,6 +75,69 @@ describe('stringifyForModel', () => {
})
})
test('pruneEmpty', () => {
expect(
pruneEmpty({
a: 1,
b: { foo: true },
c: [true],
d: 'foo',
e: null,
f: undefined
})
).toEqual({
a: 1,
b: { foo: true },
c: [true],
d: 'foo'
})
expect(pruneEmpty({ a: 0, b: {}, c: [], d: '' })).toEqual({
a: 0
})
expect(pruneEmpty({ b: {}, c: [], d: '' })).toEqual({})
expect(
pruneEmpty({
a: null,
b: { foo: [{}], bar: [null, undefined, ''] },
c: ['', '', ''],
d: '',
e: undefined,
f: [],
g: {}
})
).toEqual({
b: { foo: [{}], bar: [null, undefined, ''] },
c: ['', '', '']
})
})
test('pruneEmptyDeep', () => {
expect(
pruneEmptyDeep({ a: 1, b: { foo: true }, c: [true], d: 'foo' })
).toEqual({
a: 1,
b: { foo: true },
c: [true],
d: 'foo'
})
expect(pruneEmptyDeep({ a: 0, b: {}, c: [], d: '' })).toEqual({
a: 0
})
expect(
pruneEmptyDeep({
a: null,
b: { foo: [{}], bar: [null, undefined, ''] },
c: ['', '', ''],
d: '',
e: undefined
})
).toEqual(undefined)
})
test(
'throttleKy should rate-limit requests to ky properly',
async () => {

Wyświetl plik

@ -15,8 +15,8 @@ export { default as delay } from 'delay'
* ```
*/
export const omit = <
T extends Record<any, unknown> | object,
K extends keyof T = keyof T
T extends Record<string, unknown> | object,
K extends keyof any
>(
inputObj: T,
...keys: K[]
@ -36,8 +36,8 @@ export const omit = <
* ```
*/
export const pick = <
T extends Record<any, unknown> | object,
K extends keyof T = keyof T
T extends Record<string, unknown> | object,
K extends keyof T
>(
inputObj: T,
...keys: K[]
@ -110,6 +110,50 @@ export function pruneEmpty<T extends Record<string, any>>(
) as NonNullable<T>
}
export function pruneEmptyDeep<T>(
value?: T
):
| undefined
| (T extends Record<string, any>
? { [K in keyof T]: Exclude<T[K], undefined | null> }
: T extends Array<infer U>
? Array<Exclude<U, undefined | null>>
: Exclude<T, null>) {
if (value === undefined || value === null) return undefined
if (typeof value === 'string') {
if (!value) return undefined
return value as any
}
if (Array.isArray(value)) {
if (!value.length) return undefined
value = value
.map((v) => pruneEmptyDeep(v))
.filter((v) => v !== undefined) as any
if (!value || !Array.isArray(value) || !value.length) return undefined
return value as any
}
if (typeof value === 'object') {
if (!Object.keys(value).length) return undefined
value = Object.fromEntries(
Object.entries(value)
.map(([k, v]) => [k, pruneEmptyDeep(v)])
.filter(([, v]) => v !== undefined)
)
if (!value || !Object.keys(value).length) return undefined
return value as any
}
return value as any
}
export function getEnv(name: string): string | undefined {
try {
return typeof process !== 'undefined'

Wyświetl plik

@ -22,10 +22,6 @@
"strict": true,
"useDefineForClassFields": true,
"verbatimModuleSyntax": true
// NOTE: these are deprecated
// "experimentalDecorators": true,
// "emitDecoratorMetadata": true,
},
"include": ["src"]
}