2

I am new to typescript and in a learning phase. I am trying to create a generic to enforce the following condition

Consider I have a empty object

const data = {}

I need to create a generic which will check the following conditions

Check if its an object if yes, then check if there is any data inside it , else return false

Thanks in advance

3 Answers 3

9

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 ?

Sign up to request clarification or add additional context in comments.

Comments

-2

const data = {};
console.log("Check if object is empty", Object.keys(data).length == 0);
console.log("Check if it is object", typeof data === "object");

Comments

-2
const emptyObject = (data:Object) => {
    if(typeof data == "object"){
        if(Object.keys(data).length == 0){
            console.log("Empty Object");
            return true;
        }
        else{
            console.log("Not Empty Object");
        }
    }
    else{
        console.log("Not an Object");
    }
    return false;
} 

Here are some examples and the logs generated.

EXAMPLES

console.log(emptyObject({}));
console.log(emptyObject("acd"));
console.log(emptyObject({
    "acd": 1
}));

LOGS

[LOG]: "Empty Object" 
[LOG]: true 
[LOG]: "Not an Object" 
[LOG]: false 
[LOG]: "Not Empty Object" 
[LOG]: false

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.