Skip to content

Instantly share code, notes, and snippets.

@davestewart
Created September 14, 2022 12:17
Show Gist options
  • Save davestewart/f44317a2a270c00fc2ede1017b426f47 to your computer and use it in GitHub Desktop.
Save davestewart/f44317a2a270c00fc2ede1017b426f47 to your computer and use it in GitHub Desktop.
Clean object function in TypeScript
export function isObject (value?: unknown): boolean {
return !!value && typeof value === 'object'
}
export function isPlainObject (value?: unknown): boolean {
return isObject(value) && !Array.isArray(value)
}
export function isEmpty (value?: unknown): boolean {
if (value === null || value === undefined) {
return true
}
if (Array.isArray(value)) {
return value.length === 0
}
if (typeof value === 'object') {
return Object.keys(value).length === 0
}
if (typeof value === 'string') {
return value.trim() === ''
}
return false
}
export function clean<T extends Record<string, unknown>> (source: T, deep: boolean): Partial<T> | undefined
export function clean<T extends Record<string, unknown>> (source: T): Partial<T>
export function clean<T extends unknown[]> (source: T, deep: boolean): T[] | undefined
export function clean<T extends unknown[]> (source: T): T[]
export function clean<T> (source: T, deep: boolean): T | undefined
export function clean<T> (source: T): T
export function clean<T> (source: T, deep = false) {
// array
if (Array.isArray(source)) {
const cleaned = source
.map(value => clean(value, deep))
.filter(e => !isEmpty(e))
return deep
? isEmpty(cleaned)
? undefined
: cleaned
: cleaned
}
// object
if (isPlainObject(source)) {
type K = keyof T
type P = Pick<T, K>
const cleaned = Object.keys(source).reduce((output: P, key: string) => {
// initial input
const input: unknown = source[key as K]
// recursively clean sub-objects
const value = deep
? clean(input, deep)
: input
// only add non-empty values
if (!isEmpty(value)) {
Object.assign(output, { [key]: value })
}
return output
}, {} as P)
return deep
? isEmpty(cleaned)
? undefined
: cleaned
: cleaned
}
// determine return type
return deep
? isEmpty(source)
? undefined
: source
: source
}
const input = {
a: undefined,
b: null,
c: true,
d: false,
e: {
a: null,
b: 1,
c: [
undefined,
null,
true,
{
a: undefined,
}
]
},
f: [[0, undefined, 1]]
}
console.log(clean(input))
console.log(clean(input, true))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment