An “items.map is not a function” error often leads to an empty-array fallback. But turning a malformed API response into [] can make users believe their data does not exist. Separate array detection, element validation and error presentation.
1. Use the right array check
console.log(Array.isArray([])); // true
console.log(Array.isArray({ length: 0 })); // false
console.log(Array.isArray(null)); // false
console.log(Array.isArray('[]')); // false
The MDN Array.isArray reference documents checking whether a value is an Array. A length property or list-like log output is insufficient. The string '[]' is still a string.
After JSON.parse or response.json, inspect the resulting value rather than decoding it again blindly. Valid JSON can represent an object, null or a scalar instead of a list.
2. Validate elements against a contract
Suppose the response is an object with an items array. Each record requires a positive safe-integer id and a name string that is nonblank after trimming. This is an example contract; string identifiers require different rules.
function readItems(payload) {
if (payload === null || typeof payload !== 'object'
|| Array.isArray(payload) || !Array.isArray(payload.items)) {
throw new TypeError('Expected an object with an items array');
}
const result = [];
for (const item of payload.items) {
if (item === null || typeof item !== 'object'
|| Array.isArray(item)
|| !Number.isSafeInteger(item.id) || item.id <= 0
|| typeof item.name !== 'string' || item.name.trim() === '') {
throw new TypeError('Invalid item');
}
result.push({ id: item.id, name: item.name });
}
return result;
}
This function targets decoded JSON, not arbitrary JavaScript objects. It produces records containing only id and name. It does not silently discard invalid entries, check duplicate IDs or trim returned names. Make those choices explicit in production.
3. Empty is different from unreadable
Under this contract, {items: []} is valid and empty. {items: null}, {} and {items: {}} are invalid. Converting all of them into [] removes the distinction between no records and a failure to load records.
Provide a separate error state so users know to retry or seek support. Log minimal diagnostic context rather than complete responses containing personal information. Shape validation also does not replace HTTP-status checks or network-error handling.
4. Validation is not sanitization
A type-valid name can still contain HTML characters. Render it as text with appropriate escaping; passing readItems is not permission to insert it into innerHTML.
Frontend validation detects integration defects and protects interface behavior. It does not grant authorization, replace backend enforcement or establish business correctness.
5. Test cases
- {items: []} returns an empty array.
- A valid record returns its id and name.
- Missing items, null and object values throw.
- Null entries, missing names and string IDs are rejected.
- One invalid entry does not silently produce partial success.
- The interface distinguishes empty and failed results.
The goal is not an Array.isArray check on every line. Validate at the application boundary, produce a stable internal structure and preserve errors instead of concealing them with defaults.




No comments yet. Be the first to share your thoughts.