I have created a customized function similar to Ramda's isEmpty, tailored to meet my specific requirements:
/**
* Checks if a value is empty.
* Returns true for null, undefined, empty strings, empty Sets, empty Maps, and objects without properties.
* @param input Can be any type of value.
* @example
*
* isEmpty([1, 2, 3]); //=> false
* isEmpty([]); //=> true
*
* isEmpty(''); //=> true
*
* isEmpty(null); //=> true
* isEmpty(undefined); //=> true
*
* isEmpty({}); //=> true
*
* isEmpty(new Set([1, 2, 3])); //=> false
* isEmpty(new Set()); //=> true
*
* isEmpty(0); //=> false
*
* isEmpty(new Date()); //=> true
* isEmpty(Date.now()); //=> false
*/
export const isEmpty = (input: any): boolean => {
const isMapOrSet = input instanceof Map || input instanceof Set;
return input === null
|| input === undefined
|| (input instanceof String ? input.length > 0 : false)
|| (isMapOrSet ? input.size === 0 : false)
|| (!isMapOrSet && input instanceof Object ? Object.keys(input).length === 0 : false);
};
While using this function is straightforward, I find the boolean
return type problematic as TypeScript struggles to infer null checks provided by the function.
For instance, the following code is valid but TypeScript raises a warning about potential null at the someResult[0]
call.
const someResult: [] | null = getStuffFromAPI();
const x = isEmpty(someResult)
? {}
: someResult[0]; // TypeScript alerts about possible _null_ here.
Hence, my question is: How can I enhance the function's signature to help TypeScript accurately deduce the return type?
I attempted to define a custom return type using conditional types, yet I struggled to implement it correctly.
To provide clarity on what I seek, here's some pseudo code (please note that HasNoElements
and IsEmpty
are not real in TS):
type IsEmpty<T> =
T extends null | undefined ? true :
T extends Map & HasNoElements ? true :
T extends Set & HasNoElements ? true :
T extends String & IsEmpty ? true :
T extends Object & IsEmpty ? true :
false;
I might be overcomplicating things, but I wish to expand my knowledge in this area.