When building admin dashboards or analytics views, it's common to report on user activity — especially by user roles like admin, editor, or viewer. In this post, we'll walk through a small utility function in TypeScript that counts active users grouped by their role, and we'll include unit tests to ensure it behaves correctly.
The Function: countActiveUsersByRole
Let's say you receive a list of user objects like this:
{
id: 1,
name: "Alice",
role: "admin",
isActive: true
}
Your goal is to count how many active users exist for each role. Here's the function that does exactly that:
export const countActiveUsersByRole = (
users:
| Array<{
id: number;
name: string;
role: string;
isActive: boolean;
}>
| null
| undefined
) => {
if (!Array.isArray(users)) return {};
return users
.filter((user) => user.isActive)
.reduce<Record<string, number>>((acc, user) => {
acc[user.role] = (acc[user.role] || 0) + 1;
return acc;
}, {});
};
How it works
- Guard Clause: Returns an empty object if users is null, undefined, or not an array.
- Filter: Keeps only users where isActive === true.
- Reduce: Accumulates a count of active users by their role.
Unit Tests with Jest
To make sure our function behaves correctly, here are some test cases:
import { countActiveUsersByRole } from "./countActiveUsersByRole";
describe("countActiveUsersByRole", () => {
const users = [
{ id: 1, name: "Alice", role: "admin", isActive: true },
{ id: 2, name: "Bob", role: "editor", isActive: false },
{ id: 3, name: "Charlie", role: "admin", isActive: true },
{ id: 4, name: "Dave", role: "editor", isActive: true },
{ id: 5, name: "Eve", role: "viewer", isActive: true },
];
it("returns active users with role as key and value as count", () => {
const result = countActiveUsersByRole(users);
expect(result).toEqual({ admin: 2, editor: 1, viewer: 1 });
});
it("returns an empty object if non-array is passed", () => {
expect(countActiveUsersByRole(null)).toEqual({});
});
});
Explanation of Tests
- Test 1: Ensures active users are counted by their role.
- Test 2: Ensures the function safely handles null or invalid input.
Bonus: Why This Is Useful
This utility function is perfect for use in:
- Admin dashboards
- Analytics reports
- Role-based access summaries
It's also type-safe, defensive (handles edge cases), and easy to test.
Wrap-up
This function is a great example of clean functional logic combined with type safety and unit testing. It's small but solves a real-world need in many backend and frontend apps.
Need this in your project? Just copy and paste the code — and don't forget to add tests.