You can use this utility to check whether object type is empty or not:
// credits goes to https://github.com/microsoft/TypeScript/issues/23182#issuecomment-379091887
type IsEmptyObject<Obj extends Record<PropertyKey, unknown>> =
[keyof Obj] extends [never] ? true : false
type Test = IsEmptyObject<{}> // true
type Test2 = IsEmptyObject<{ age: 42 }> // false
If Obj does not have any keys then keyof Obj returns never.
Our goal is to check whether it returns never or not.
In order to check it, we need to stop distributivity.
If keyof Obj returns never then our conditional type IsEmptyObject returns true.
If you want to use it in a function, consider this example:
type IsEmptyObject<Obj extends Record<PropertyKey, unknown>> =
[keyof Obj] extends [never] ? true : false
function isEmpty<Obj extends Record<PropertyKey, unknown>>(obj: Obj): IsEmptyObject<Obj>
function isEmpty<Obj extends Record<PropertyKey, unknown>>(obj: Obj) {
return Object.keys(obj).length === 0
}
const result = isEmpty({}) // true
const result2 = isEmpty({ age: 42 }) // false
Playground
Also you need to be aware that it works only with literal types.
If you want to make it work with higher order function and I bet you want, please consider this example:
type IsEmptyObject<Obj extends Record<PropertyKey, unknown>, Keys = keyof Obj> =
PropertyKey extends Keys ? boolean : [keyof Obj] extends [never] ? true : false
function isEmpty<Obj extends Record<PropertyKey, unknown>>(obj: Obj): IsEmptyObject<Obj>
function isEmpty<Obj extends Record<PropertyKey, unknown>>(obj: Obj) {
return Object.keys(obj).length === 0
}
const higherOrderFunction = (obj: Record<PropertyKey, unknown>) => {
const test = isEmpty(obj) // boolean
return test
}
const result3 = higherOrderFunction({ age: 2 }) // boolean
If isEmpty is unable to infer literal type, it will return boolean by the default, since you never know what you can get in higher order function.
If you infer obj argument in higherOrderFunction, isEmpty in turn will be able to infer argument too.
const higherOrderFunction = <T extends Record<PropertyKey, unknown>>(obj: T) => {
const test = isEmpty(obj) // IsEmptyObject<T, keyof T>
return test
}
const result3 = higherOrderFunction({ age: 2 }) // false
const result4 = higherOrderFunction({ }) // true
Playground
I'm not sure what you mean: then check if there is any data inside it.
Question:
Let's say we have this object: {age: undefined}. Do you consider it with data or not ?