skip to content
Alvin Lucillo

Check undefined and zero length

/ 2 min read

Suppose you have this interface and you need to ensure that you fail the validation if the items is undefined or empty.

interface Test {
	items?: string[];
}

Maybe you’ll come up with a condition similar to below. And yes, it works because only t4 passed the validation. But let’s see if we can simplify it.

const t1: Test = {};
const t2: Test = { items: undefined };
const t3: Test = { items: [] };
const t4: Test = { items: ["1"] };

const tests: Test[] = [t1, t2, t3, t4];
tests.forEach((t, i) => {
	testCondition(t, i + 1);
});

function testCondition(t: Test, i: number) {
	if (!t?.items || t.items.length === 0) {
		console.log(i, "failed validation");
	}
}

/*
[LOG]: 1,  "failed validation" 
[LOG]: 2,  "failed validation" 
[LOG]: 3,  "failed validation" 
*/

Let’s try optional chaining here. This one doesn’t work; as we can see, the only failing test is the 3rd one. This is because t?.items?.length evaluates to undefined, so length is not being checked, thereby the condition doesn’t proceed. Okay, let’s try one more.

function testCondition(t: Test, i: number) {
	if (t?.items?.length === 0) {
		console.log(i, "failed validation");
	}
}

/*
[LOG]: 3,  "failed validation" 
*/

Nice, this one worked, and we achieve a shorter condition. So we get that for this condition alone (!t?.items?.length), if items is undefined, then definitely the condition be true since ! inverts the undefined, a falsy value. Falsy means it’s essentially false, but not “false”. However, what about when items is empty? The condition !t?.items?.length will return 0, another falsy value, which becomes true when inverted.

function testCondition(t: Test, i: number) {
	if (!t?.items?.length) {
		console.log(i, "failed validation");
	}
}

/*
[LOG]: 1,  "failed validation" 
[LOG]: 2,  "failed validation" 
[LOG]: 3,  "failed validation" 
*/

Full code here.